Skip to main content

Overview

BR-ACC uses Neo4j’s Cypher query language to navigate the graph database. Cypher is a declarative pattern-matching language that makes it intuitive to query connected data.

Basic Query Structure

A typical Cypher query follows this pattern:
MATCH (pattern)
WHERE (conditions)
RETURN (results)

Finding Entities

Find Company by CNPJ

The most common query is looking up a company by its unique identifier:
MATCH (c:Company)
WHERE c.cnpj = $company_identifier
   OR c.cnpj = $company_identifier_formatted
RETURN c, labels(c) AS entity_labels, elementId(c) AS entity_id
LIMIT 1
From public_company_lookup.cypher - Production code used in the BR-ACC API

Find Person or Company by Document

Search for either a Person (CPF) or Company (CNPJ):
MATCH (e)
WHERE (e:Person AND (e.cpf = $identifier OR e.cpf = $identifier_formatted))
   OR (e:Company AND (e.cnpj = $identifier OR e.cnpj = $identifier_formatted))
RETURN e, labels(e) AS entity_labels, elementId(e) AS entity_id
LIMIT 1
From entity_lookup.cypher

Find Any Entity by ID

BR-ACC supports multiple entity types with different ID fields:
MATCH (e) 
WHERE (e.cpf = $id OR e.cnpj = $id
  OR e.contract_id = $id OR e.sanction_id = $id
  OR e.amendment_id = $id OR e.cnes_code = $id
  OR e.finance_id = $id OR e.embargo_id = $id
  OR e.school_id = $id OR e.convenio_id = $id
  OR e.partner_id = $id OR e.stats_id = $id 
  OR elementId(e) = $id)
AND (e:Person OR e:Partner OR e:Company OR e:Contract 
  OR e:Sanction OR e:Election OR e:Amendment OR e:Finance 
  OR e:Embargo OR e:Health OR e:Education OR e:Convenio 
  OR e:LaborStats OR e:PublicOffice)
RETURN e, labels(e) AS entity_labels
LIMIT 1
From entity_by_id.cypher - Supports all entity types in BR-ACC
BR-ACC includes a full-text search index across multiple entity types:
CALL db.index.fulltext.queryNodes("entity_search", $query)
YIELD node, score
WITH node, score, labels(node) AS node_labels
WHERE NONE(label IN node_labels WHERE label IN ['User', 'Investigation', 'Annotation', 'Tag'])
  AND (NOT $hide_person_entities OR NONE(label IN node_labels WHERE label IN ['Person', 'Partner']))
  AND ($entity_type IS NULL
       OR ANY(label IN node_labels WHERE toLower(label) = $entity_type))
RETURN node, score, node_labels,
       elementId(node) AS node_id,
       coalesce(node.cpf, node.cnpj, node.contract_id, 
                node.sanction_id, node.amendment_id, node.cnes_code, 
                node.finance_id, node.embargo_id, node.school_id, 
                node.convenio_id, node.stats_id, elementId(node)) AS document_id
ORDER BY score DESC
SKIP $skip
LIMIT $limit
From search.cypher - Searches across name, razao_social, CPF, CNPJ, and other fields

Node Labels

BR-ACC uses the following primary node labels:

Person

Individual with CPF identifier

Company

Legal entity with CNPJ

Partner

Company partner/shareholder

Contract

Government contract

Sanction

Administrative sanction

Embargo

Environmental embargo

Amendment

Budget amendment

Finance

Financial transaction/debt

Election

Electoral data

Using Parameters

Always use parameterized queries to prevent injection attacks and improve query plan caching.
# Python example with neo4j driver
result = session.run(
    "MATCH (c:Company) WHERE c.cnpj = $cnpj RETURN c",
    cnpj="12345678000190"
)

Next Steps

Common Patterns

Learn query patterns for networks and relationships

Performance

Optimize queries with indexes and constraints

Build docs developers (and LLMs) love