Skip to main content
This page documents the complete Neo4j schema for BR-ACC, derived from /infra/neo4j/init.cypher.

Uniqueness Constraints

Uniqueness constraints ensure data integrity and enable fast lookups.
// Person
CREATE CONSTRAINT person_cpf_unique IF NOT EXISTS
  FOR (p:Person) REQUIRE p.cpf IS UNIQUE;

// Partner
CREATE CONSTRAINT partner_id_unique IF NOT EXISTS
  FOR (p:Partner) REQUIRE p.partner_id IS UNIQUE;

// Company
CREATE CONSTRAINT company_cnpj_unique IF NOT EXISTS
  FOR (c:Company) REQUIRE c.cnpj IS UNIQUE;
// Contract
CREATE CONSTRAINT contract_contract_id_unique IF NOT EXISTS
  FOR (c:Contract) REQUIRE c.contract_id IS UNIQUE;

// Sanction
CREATE CONSTRAINT sanction_sanction_id_unique IF NOT EXISTS
  FOR (s:Sanction) REQUIRE s.sanction_id IS UNIQUE;

// PublicOffice
CREATE CONSTRAINT public_office_id_unique IF NOT EXISTS
  FOR (po:PublicOffice) REQUIRE po.office_id IS UNIQUE;

// Amendment
CREATE CONSTRAINT amendment_id_unique IF NOT EXISTS
  FOR (a:Amendment) REQUIRE a.amendment_id IS UNIQUE;

// Convenio
CREATE CONSTRAINT convenio_id_unique IF NOT EXISTS
  FOR (c:Convenio) REQUIRE c.convenio_id IS UNIQUE;

// Bid
CREATE CONSTRAINT bid_id_unique IF NOT EXISTS
  FOR (b:Bid) REQUIRE b.bid_id IS UNIQUE;

// DOUAct
CREATE CONSTRAINT dou_act_id_unique IF NOT EXISTS
  FOR (d:DOUAct) REQUIRE d.act_id IS UNIQUE;
// Health
CREATE CONSTRAINT health_cnes_code_unique IF NOT EXISTS
  FOR (h:Health) REQUIRE h.cnes_code IS UNIQUE;

// Education
CREATE CONSTRAINT education_school_id_unique IF NOT EXISTS
  FOR (e:Education) REQUIRE e.school_id IS UNIQUE;

// Finance
CREATE CONSTRAINT finance_id_unique IF NOT EXISTS
  FOR (f:Finance) REQUIRE f.finance_id IS UNIQUE;

// Embargo
CREATE CONSTRAINT embargo_id_unique IF NOT EXISTS
  FOR (e:Embargo) REQUIRE e.embargo_id IS UNIQUE;

// LaborStats
CREATE CONSTRAINT laborstats_id_unique IF NOT EXISTS
  FOR (l:LaborStats) REQUIRE l.stats_id IS UNIQUE;

// LaborMovement
CREATE CONSTRAINT labor_movement_id_unique IF NOT EXISTS
  FOR (lm:LaborMovement) REQUIRE lm.movement_id IS UNIQUE;
// OffshoreEntity
CREATE CONSTRAINT offshore_entity_id_unique IF NOT EXISTS
  FOR (o:OffshoreEntity) REQUIRE o.offshore_id IS UNIQUE;

// OffshoreOfficer
CREATE CONSTRAINT offshore_officer_id_unique IF NOT EXISTS
  FOR (o:OffshoreOfficer) REQUIRE o.offshore_officer_id IS UNIQUE;

// GlobalPEP
CREATE CONSTRAINT global_pep_id_unique IF NOT EXISTS
  FOR (g:GlobalPEP) REQUIRE g.pep_id IS UNIQUE;

// InternationalSanction
CREATE CONSTRAINT international_sanction_id_unique IF NOT EXISTS
  FOR (s:InternationalSanction) REQUIRE s.sanction_id IS UNIQUE;
// Expense
CREATE CONSTRAINT expense_id_unique IF NOT EXISTS
  FOR (e:Expense) REQUIRE e.expense_id IS UNIQUE;

// GovCardExpense
CREATE CONSTRAINT gov_card_expense_id_unique IF NOT EXISTS
  FOR (g:GovCardExpense) REQUIRE g.expense_id IS UNIQUE;

// GovTravel
CREATE CONSTRAINT gov_travel_id_unique IF NOT EXISTS
  FOR (t:GovTravel) REQUIRE t.travel_id IS UNIQUE;

// PEPRecord
CREATE CONSTRAINT pep_record_id_unique IF NOT EXISTS
  FOR (p:PEPRecord) REQUIRE p.pep_id IS UNIQUE;

// CPI
CREATE CONSTRAINT cpi_id_unique IF NOT EXISTS
  FOR (c:CPI) REQUIRE c.cpi_id IS UNIQUE;

// Inquiry
CREATE CONSTRAINT inquiry_id_unique IF NOT EXISTS
  FOR (i:Inquiry) REQUIRE i.inquiry_id IS UNIQUE;

// InquiryRequirement
CREATE CONSTRAINT inquiry_requirement_id_unique IF NOT EXISTS
  FOR (r:InquiryRequirement) REQUIRE r.requirement_id IS UNIQUE;

// InquirySession
CREATE CONSTRAINT inquiry_session_id_unique IF NOT EXISTS
  FOR (s:InquirySession) REQUIRE s.session_id IS UNIQUE;
// MunicipalFinance
CREATE CONSTRAINT municipal_finance_id_unique IF NOT EXISTS
  FOR (m:MunicipalFinance) REQUIRE m.finance_id IS UNIQUE;

// MunicipalBid
CREATE CONSTRAINT municipal_bid_id_unique IF NOT EXISTS
  FOR (b:MunicipalBid) REQUIRE b.municipal_bid_id IS UNIQUE;

// MunicipalContract
CREATE CONSTRAINT municipal_contract_id_unique IF NOT EXISTS
  FOR (c:MunicipalContract) REQUIRE c.municipal_contract_id IS UNIQUE;

// MunicipalBidItem
CREATE CONSTRAINT municipal_bid_item_id_unique IF NOT EXISTS
  FOR (i:MunicipalBidItem) REQUIRE i.municipal_item_id IS UNIQUE;

// MunicipalGazetteAct
CREATE CONSTRAINT municipal_gazette_act_id_unique IF NOT EXISTS
  FOR (a:MunicipalGazetteAct) REQUIRE a.municipal_gazette_act_id IS UNIQUE;
// TaxWaiver
CREATE CONSTRAINT tax_waiver_id_unique IF NOT EXISTS
  FOR (t:TaxWaiver) REQUIRE t.waiver_id IS UNIQUE;

// DeclaredAsset
CREATE CONSTRAINT declared_asset_id_unique IF NOT EXISTS
  FOR (d:DeclaredAsset) REQUIRE d.asset_id IS UNIQUE;

// Holding
CREATE CONSTRAINT holding_rel_id_unique IF NOT EXISTS
  FOR (h:Holding) REQUIRE h.holding_id IS UNIQUE;

// Fund
CREATE CONSTRAINT fund_cnpj_unique IF NOT EXISTS
  FOR (f:Fund) REQUIRE f.fund_cnpj IS UNIQUE;

// PartyMembership
CREATE CONSTRAINT party_membership_id_unique IF NOT EXISTS
  FOR (pm:PartyMembership) REQUIRE pm.membership_id IS UNIQUE;
// SourceDocument
CREATE CONSTRAINT source_document_id_unique IF NOT EXISTS
  FOR (s:SourceDocument) REQUIRE s.doc_id IS UNIQUE;

// IngestionRun
CREATE CONSTRAINT ingestion_run_id_unique IF NOT EXISTS
  FOR (r:IngestionRun) REQUIRE r.run_id IS UNIQUE;

// TemporalViolation
CREATE CONSTRAINT temporal_violation_id_unique IF NOT EXISTS
  FOR (t:TemporalViolation) REQUIRE t.violation_id IS UNIQUE;

// User
CREATE CONSTRAINT user_email_unique IF NOT EXISTS
  FOR (u:User) REQUIRE u.email IS UNIQUE;

Property Indexes

Property indexes accelerate filtering and sorting queries.
// Name-based search
CREATE INDEX person_name IF NOT EXISTS
  FOR (p:Person) ON (p.name);

CREATE INDEX person_name_uf IF NOT EXISTS
  FOR (p:Person) ON (p.name, p.uf);

// CPF matching strategies
CREATE INDEX person_cpf_middle6 IF NOT EXISTS
  FOR (p:Person) ON (p.cpf_middle6);

CREATE INDEX person_cpf_partial IF NOT EXISTS
  FOR (p:Person) ON (p.cpf_partial);

// Cross-source identifiers
CREATE INDEX person_author_key IF NOT EXISTS
  FOR (p:Person) ON (p.author_key);

CREATE INDEX person_sq_candidato IF NOT EXISTS
  FOR (p:Person) ON (p.sq_candidato);

CREATE INDEX person_deputy_id IF NOT EXISTS
  FOR (p:Person) ON (p.deputy_id);

CREATE INDEX person_servidor_id IF NOT EXISTS
  FOR (p:Person) ON (p.servidor_id);
CREATE INDEX partner_name IF NOT EXISTS
  FOR (p:Partner) ON (p.name);

CREATE INDEX partner_doc_partial IF NOT EXISTS
  FOR (p:Partner) ON (p.doc_partial);

CREATE INDEX partner_name_doc_partial IF NOT EXISTS
  FOR (p:Partner) ON (p.name, p.doc_partial);
CREATE INDEX company_razao_social IF NOT EXISTS
  FOR (c:Company) ON (c.razao_social);

CREATE INDEX company_cnae_principal IF NOT EXISTS
  FOR (c:Company) ON (c.cnae_principal);
CREATE INDEX contract_value IF NOT EXISTS
  FOR (c:Contract) ON (c.value);

CREATE INDEX contract_object IF NOT EXISTS
  FOR (c:Contract) ON (c.object);

CREATE INDEX contract_contracting_org IF NOT EXISTS
  FOR (c:Contract) ON (c.contracting_org);

CREATE INDEX contract_date IF NOT EXISTS
  FOR (c:Contract) ON (c.date);
// Sanction
CREATE INDEX sanction_type IF NOT EXISTS
  FOR (s:Sanction) ON (s.type);

CREATE INDEX sanction_date_start IF NOT EXISTS
  FOR (s:Sanction) ON (s.date_start);

// Election
CREATE INDEX election_year IF NOT EXISTS
  FOR (e:Election) ON (e.year);

CREATE INDEX election_composite IF NOT EXISTS
  FOR (e:Election) ON (e.year, e.cargo, e.uf, e.municipio);
CREATE INDEX amendment_function IF NOT EXISTS
  FOR (a:Amendment) ON (a.function);

CREATE INDEX amendment_value_committed IF NOT EXISTS
  FOR (a:Amendment) ON (a.value_committed);
CREATE INDEX finance_type IF NOT EXISTS
  FOR (f:Finance) ON (f.type);

CREATE INDEX finance_value IF NOT EXISTS
  FOR (f:Finance) ON (f.value);

CREATE INDEX finance_date IF NOT EXISTS
  FOR (f:Finance) ON (f.date);

CREATE INDEX finance_source IF NOT EXISTS
  FOR (f:Finance) ON (f.source);
// Health
CREATE INDEX health_name IF NOT EXISTS
  FOR (h:Health) ON (h.name);

CREATE INDEX health_uf IF NOT EXISTS
  FOR (h:Health) ON (h.uf);

CREATE INDEX health_municipio IF NOT EXISTS
  FOR (h:Health) ON (h.municipio);

CREATE INDEX health_atende_sus IF NOT EXISTS
  FOR (h:Health) ON (h.atende_sus);

// Education
CREATE INDEX education_name IF NOT EXISTS
  FOR (e:Education) ON (e.name);

// Embargo
CREATE INDEX embargo_uf IF NOT EXISTS
  FOR (e:Embargo) ON (e.uf);

CREATE INDEX embargo_biome IF NOT EXISTS
  FOR (e:Embargo) ON (e.biome);

// Convenio
CREATE INDEX convenio_date_published IF NOT EXISTS
  FOR (c:Convenio) ON (c.date_published);

// LaborStats
CREATE INDEX laborstats_uf IF NOT EXISTS
  FOR (l:LaborStats) ON (l.uf);

CREATE INDEX laborstats_cnae_subclass IF NOT EXISTS
  FOR (l:LaborStats) ON (l.cnae_subclass);
// OffshoreEntity
CREATE INDEX offshore_entity_name IF NOT EXISTS
  FOR (o:OffshoreEntity) ON (o.name);

CREATE INDEX offshore_entity_jurisdiction IF NOT EXISTS
  FOR (o:OffshoreEntity) ON (o.jurisdiction);

// OffshoreOfficer
CREATE INDEX offshore_officer_name IF NOT EXISTS
  FOR (o:OffshoreOfficer) ON (o.name);

// GlobalPEP
CREATE INDEX global_pep_name IF NOT EXISTS
  FOR (g:GlobalPEP) ON (g.name);

CREATE INDEX global_pep_country IF NOT EXISTS
  FOR (g:GlobalPEP) ON (g.country);
// CVMProceeding
CREATE INDEX cvm_proceeding_date IF NOT EXISTS
  FOR (c:CVMProceeding) ON (c.date);

// BCBPenalty
CREATE INDEX bcb_penalty_type IF NOT EXISTS
  FOR (b:BCBPenalty) ON (b.penalty_type);

CREATE INDEX bcb_penalty_date IF NOT EXISTS
  FOR (b:BCBPenalty) ON (b.decision_date);

// LegalCase
CREATE INDEX legal_case_type IF NOT EXISTS
  FOR (l:LegalCase) ON (l.type);

CREATE INDEX legal_case_date IF NOT EXISTS
  FOR (l:LegalCase) ON (l.date);

// InternationalSanction
CREATE INDEX international_sanction_source IF NOT EXISTS
  FOR (s:InternationalSanction) ON (s.source);
// Expense
CREATE INDEX expense_deputy_id IF NOT EXISTS
  FOR (e:Expense) ON (e.deputy_id);

CREATE INDEX expense_date IF NOT EXISTS
  FOR (e:Expense) ON (e.date);

CREATE INDEX expense_type IF NOT EXISTS
  FOR (e:Expense) ON (e.type);

// GovCardExpense
CREATE INDEX gov_card_expense_date IF NOT EXISTS
  FOR (g:GovCardExpense) ON (g.date);

CREATE INDEX gov_card_expense_value IF NOT EXISTS
  FOR (g:GovCardExpense) ON (g.value);

// GovTravel
CREATE INDEX gov_travel_date IF NOT EXISTS
  FOR (t:GovTravel) ON (t.start_date);

// TaxWaiver
CREATE INDEX tax_waiver_value IF NOT EXISTS
  FOR (t:TaxWaiver) ON (t.value);

// PEPRecord
CREATE INDEX pep_record_name IF NOT EXISTS
  FOR (p:PEPRecord) ON (p.name);

CREATE INDEX pep_record_role IF NOT EXISTS
  FOR (p:PEPRecord) ON (p.role);

CREATE INDEX pep_record_org IF NOT EXISTS
  FOR (p:PEPRecord) ON (p.org);

// Expulsion
CREATE INDEX expulsion_date IF NOT EXISTS
  FOR (e:Expulsion) ON (e.date);

// LeniencyAgreement
CREATE INDEX leniency_date IF NOT EXISTS
  FOR (l:LeniencyAgreement) ON (l.date);

// BarredNGO
CREATE INDEX barred_ngo_cnpj IF NOT EXISTS
  FOR (b:BarredNGO) ON (b.cnpj);

// DeclaredAsset
CREATE INDEX declared_asset_type IF NOT EXISTS
  FOR (d:DeclaredAsset) ON (d.asset_type);

CREATE INDEX declared_asset_value IF NOT EXISTS
  FOR (d:DeclaredAsset) ON (d.asset_value);

CREATE INDEX declared_asset_year IF NOT EXISTS
  FOR (d:DeclaredAsset) ON (d.election_year);
// Bid
CREATE INDEX bid_date IF NOT EXISTS
  FOR (b:Bid) ON (b.date);

CREATE INDEX bid_modality IF NOT EXISTS
  FOR (b:Bid) ON (b.modality);

// Fund
CREATE INDEX fund_name IF NOT EXISTS
  FOR (f:Fund) ON (f.fund_name);

CREATE INDEX fund_type IF NOT EXISTS
  FOR (f:Fund) ON (f.fund_type);

// DOUAct
CREATE INDEX dou_act_date IF NOT EXISTS
  FOR (d:DOUAct) ON (d.date);

CREATE INDEX dou_act_type IF NOT EXISTS
  FOR (d:DOUAct) ON (d.act_type);
// MunicipalFinance
CREATE INDEX municipal_finance_year IF NOT EXISTS
  FOR (m:MunicipalFinance) ON (m.year);

CREATE INDEX municipal_finance_cod_ibge IF NOT EXISTS
  FOR (m:MunicipalFinance) ON (m.cod_ibge);

// MunicipalBid
CREATE INDEX municipal_bid_date IF NOT EXISTS
  FOR (b:MunicipalBid) ON (b.published_at);

// MunicipalContract
CREATE INDEX municipal_contract_date IF NOT EXISTS
  FOR (c:MunicipalContract) ON (c.signed_at);

// MunicipalGazetteAct
CREATE INDEX municipal_gazette_date IF NOT EXISTS
  FOR (a:MunicipalGazetteAct) ON (a.published_at);
CREATE INDEX inquiry_name IF NOT EXISTS
  FOR (i:Inquiry) ON (i.name);

CREATE INDEX inquiry_kind_house IF NOT EXISTS
  FOR (i:Inquiry) ON (i.kind, i.house);

CREATE INDEX inquiry_requirement_date IF NOT EXISTS
  FOR (r:InquiryRequirement) ON (r.date);

CREATE INDEX inquiry_session_date IF NOT EXISTS
  FOR (s:InquirySession) ON (s.date);

CREATE INDEX cpi_name IF NOT EXISTS
  FOR (c:CPI) ON (c.name);

CREATE INDEX cpi_date IF NOT EXISTS
  FOR (c:CPI) ON (c.date_start);
// PartyMembership
CREATE INDEX party_membership_party IF NOT EXISTS
  FOR (pm:PartyMembership) ON (pm.party);

CREATE INDEX party_membership_uf IF NOT EXISTS
  FOR (pm:PartyMembership) ON (pm.uf);

// LaborMovement
CREATE INDEX labor_movement_date IF NOT EXISTS
  FOR (lm:LaborMovement) ON (lm.movement_date);

CREATE INDEX labor_movement_type IF NOT EXISTS
  FOR (lm:LaborMovement) ON (lm.movement_type);

CREATE INDEX labor_movement_uf IF NOT EXISTS
  FOR (lm:LaborMovement) ON (lm.uf);
// SourceDocument
CREATE INDEX source_document_source_id IF NOT EXISTS
  FOR (s:SourceDocument) ON (s.source_id);

CREATE INDEX source_document_published_at IF NOT EXISTS
  FOR (s:SourceDocument) ON (s.published_at);

CREATE INDEX source_document_retrieved_at IF NOT EXISTS
  FOR (s:SourceDocument) ON (s.retrieved_at);

// IngestionRun
CREATE INDEX ingestion_run_source_id IF NOT EXISTS
  FOR (r:IngestionRun) ON (r.source_id);

CREATE INDEX ingestion_run_status IF NOT EXISTS
  FOR (r:IngestionRun) ON (r.status);

CREATE INDEX ingestion_run_started_at IF NOT EXISTS
  FOR (r:IngestionRun) ON (r.started_at);

// TemporalViolation
CREATE INDEX temporal_violation_source_id IF NOT EXISTS
  FOR (t:TemporalViolation) ON (t.source_id);

CREATE INDEX temporal_violation_event_date IF NOT EXISTS
  FOR (t:TemporalViolation) ON (t.event_date);
CREATE INDEX public_office_org IF NOT EXISTS
  FOR (po:PublicOffice) ON (po.org);
CREATE INDEX judicial_case_number IF NOT EXISTS
  FOR (j:JudicialCase) ON (j.case_number);

Relationship Indexes

Indexes on relationship properties for temporal queries.
// SOCIO_DE_SNAPSHOT temporal tracking
CREATE INDEX socio_snapshot_membership_id IF NOT EXISTS
  FOR ()-[r:SOCIO_DE_SNAPSHOT]-() ON (r.membership_id);

CREATE INDEX socio_snapshot_date IF NOT EXISTS
  FOR ()-[r:SOCIO_DE_SNAPSHOT]-() ON (r.snapshot_date);

Fulltext Search Index

Enables fast text search across all major entity types.
CREATE FULLTEXT INDEX entity_search IF NOT EXISTS
  FOR (n:Person|Partner|Company|Health|Education|Contract|Amendment|
         Convenio|Embargo|PublicOffice|OffshoreEntity|OffshoreOfficer|
         GlobalPEP|CVMProceeding|Expense|PEPRecord|Expulsion|
         LeniencyAgreement|GovCardExpense|GovTravel|TaxWaiver|LegalCase|
         DeclaredAsset|InternationalSanction|Bid|Fund|DOUAct|
         MunicipalFinance|PartyMembership|BarredNGO|BCBPenalty|
         LaborMovement|CPI|Inquiry|InquiryRequirement|InquirySession|
         MunicipalBid|MunicipalContract|MunicipalGazetteAct|JudicialCase|
         SourceDocument)
  ON EACH [
    n.name, n.razao_social, n.cpf, n.cnpj, n.doc_partial, n.doc_raw,
    n.cnes_code, n.object, n.contracting_org, n.convenente,
    n.infraction, n.org, n.function, n.jurisdiction, n.penalty_type,
    n.description, n.institution_name, n.subject, n.text, n.topic,
    n.case_number, n.url
  ];
// Search for entities matching "construcao silva"
CALL db.index.fulltext.queryNodes(
  'entity_search',
  'construcao AND silva'
) YIELD node, score
WHERE score > 1.0
RETURN labels(node)[0] as type, 
       node.name, 
       node.razao_social,
       score
ORDER BY score DESC
LIMIT 20

Schema Inspection

You can inspect the schema programmatically:
// List all constraints
SHOW CONSTRAINTS;

// List all indexes
SHOW INDEXES;

// Count nodes by label
MATCH (n)
RETURN labels(n)[0] as entity_type, count(*) as count
ORDER BY count DESC;

// Count relationships by type
MATCH ()-[r]-()
RETURN type(r) as relationship_type, count(*) as count
ORDER BY count DESC;

Performance Considerations

Index Usage: Neo4j automatically uses indexes when you filter on indexed properties. Use EXPLAIN or PROFILE to verify index usage.
Fulltext Search: Fulltext queries can be expensive. Always include a LIMIT clause and consider adding additional filters after the fulltext search.

Example: Checking Index Usage

// See query plan
EXPLAIN
MATCH (p:Person {cpf: '12345678900'})
RETURN p;

// See execution statistics
PROFILE
MATCH (c:Company)-[:VENCEU]->(ct:Contract)
WHERE ct.value > 1000000
RETURN c.razao_social, sum(ct.value) as total
ORDER BY total DESC
LIMIT 10;

Schema Source File

The complete schema is defined in:
/infra/neo4j/init.cypher
This file is applied during database initialization via Docker Compose.

Next Steps

Query Basics

Learn Cypher query language fundamentals

Common Patterns

Explore common investigation query patterns

Performance

Optimize queries for large datasets

ETL Pipelines

Understand how data flows into the graph

Build docs developers (and LLMs) love