Retrieve all relationships up to a specified depth from a central entity:
MATCH (center)WHERE elementId(center) = $entity_id AND (center:Person OR center:Partner OR center:Company OR center:Contract OR center:Sanction OR center:Election OR center:Amendment OR center:Finance OR center:Embargo OR center:Health OR center:Education OR center:Convenio OR center:LaborStats OR center:PublicOffice)OPTIONAL MATCH p=(center)-[:SOCIO_DE|DOOU|CANDIDATO_EM|VENCEU| AUTOR_EMENDA|SANCIONADA|OPERA_UNIDADE| DEVE|RECEBEU_EMPRESTIMO|EMBARGADA| MANTEDORA_DE|BENEFICIOU|GEROU_CONVENIO| SAME_AS|POSSIBLE_SAME_AS*1..4]-(connected)WHERE length(p) <= $depth AND all(x IN nodes(p) WHERE NOT (x:User OR x:Investigation OR x:Annotation OR x:Tag))WITH center, pUNWIND CASE WHEN p IS NULL THEN [] ELSE relationships(p) END AS rWITH DISTINCT center, r, startNode(r) AS src, endNode(r) AS tgtWHERE coalesce($include_probable, false) OR type(r) <> "POSSIBLE_SAME_AS"RETURN center AS e, r, CASE WHEN elementId(src) = elementId(center) THEN tgt ELSE src END AS connected, labels(center) AS source_labels, CASE WHEN elementId(src) = elementId(center) THEN labels(tgt) ELSE labels(src) END AS target_labels, type(r) AS rel_type, elementId(startNode(r)) AS source_id, elementId(endNode(r)) AS target_id, elementId(r) AS rel_id
From entity_connections.cypher - Used by the graph visualization API
Get full subgraph including all nodes and relationships:
MATCH (center)WHERE elementId(center) = $entity_id AND (center:Person OR center:Company OR center:Contract OR center:Sanction OR center:Election OR center:Amendment OR center:Finance OR center:Embargo OR center:Health OR center:Education OR center:Convenio OR center:LaborStats OR center:PublicOffice)OPTIONAL MATCH p=(center)-[:SOCIO_DE|DOOU|CANDIDATO_EM|VENCEU| AUTOR_EMENDA|SANCIONADA|OPERA_UNIDADE| DEVE|RECEBEU_EMPRESTIMO|EMBARGADA| MANTEDORA_DE|BENEFICIOU|GEROU_CONVENIO| SAME_AS|POSSIBLY_SAME_AS*1..4]-(n)WHERE length(p) <= $depth AND all(x IN nodes(p) WHERE NOT (x:User OR x:Investigation OR x:Annotation OR x:Tag))WITH center, collect(p) AS pathsWITH center, reduce(ns = [center], p IN paths | ns + CASE WHEN p IS NULL THEN [] ELSE nodes(p) END) AS raw_nodes, reduce(rs = [], p IN paths | rs + CASE WHEN p IS NULL THEN [] ELSE relationships(p) END) AS raw_relsUNWIND raw_nodes AS nWITH center, collect(DISTINCT n) AS nodes, raw_relsUNWIND CASE WHEN size(raw_rels) = 0 THEN [NULL] ELSE raw_rels END AS rWITH center, nodes, collect(DISTINCT r) AS relsRETURN nodes, [x IN rels WHERE x IS NOT NULL] AS relationships, elementId(center) AS center_id
From graph_expand.cypher - Returns complete subgraph for visualization
Detect companies that won contracts during active sanction periods:
Full Query
Explanation
MATCH (c:Company)WHERE elementId(c) = $company_id OR c.cnpj = $company_identifierCALL { WITH c MATCH (c)-[:SANCIONADA]->(s:Sanction) WHERE s.date_start IS NOT NULL AND trim(s.date_start) <> '' RETURN collect(DISTINCT { sanction_id: s.sanction_id, date_start: s.date_start, date_end: s.date_end }) AS sanctions}WITH c, sanctionsWHERE size(sanctions) > 0MATCH (c)-[:VENCEU]->(ct:Contract)WHERE ct.date IS NOT NULL AND trim(ct.date) <> '' AND any(s IN sanctions WHERE ct.date >= s.date_start AND (s.date_end IS NULL OR ct.date <= s.date_end) )WITH c, [s IN sanctions | s.sanction_id] AS sanction_ids, collect(DISTINCT ct.contract_id) AS contract_ids, sum(coalesce(ct.value, 0.0)) AS amount_total, min(ct.date) AS window_start, max(ct.date) AS window_endWITH c, sanction_ids, [x IN contract_ids WHERE x IS NOT NULL] AS contract_ids, amount_total, window_start, window_end, [x IN sanction_ids + contract_ids WHERE x IS NOT NULL] AS evidence_refsWHERE size(sanction_ids) > 0 AND size(contract_ids) > 0RETURN 'sanctioned_still_receiving' AS pattern_id, c.cnpj AS cnpj, c.razao_social AS company_name, toFloat(size(sanction_ids) + size(contract_ids)) AS risk_signal, amount_total AS amount_total, window_start AS window_start, window_end AS window_end, evidence_refs AS evidence_refs, size(evidence_refs) AS evidence_count
Pattern Detection Steps:
Find the target company
Collect all sanctions with date ranges
Find contracts won during sanction periods
Calculate total amount and evidence
Return risk signal with metadata
Risk Signal: Higher values indicate more sanctions + contracts
From public_pattern_sanctioned_still_receiving.cypher
Find companies with excessive market share in specific government organizations:
MATCH (c:Company)WHERE elementId(c) = $company_idMATCH (c)-[:VENCEU]->(ct:Contract)WHERE ct.contracting_org IS NOT NULL AND ct.value IS NOT NULLWITH c, ct.contracting_org AS org, sum(coalesce(ct.value, 0.0)) AS company_org_totalCALL { WITH org MATCH (:Company)-[:VENCEU]->(org_ct:Contract) WHERE org_ct.contracting_org = org AND org_ct.value IS NOT NULL RETURN sum(coalesce(org_ct.value, 0.0)) AS org_total}WITH c, org, company_org_total, org_totalWHERE org_total > 0 AND (company_org_total / org_total) >= toFloat($pattern_share_threshold)WITH c, collect(DISTINCT org) AS risky_orgsWHERE size(risky_orgs) > 0MATCH (c)-[:VENCEU]->(risk_ct:Contract)WHERE risk_ct.contracting_org IN risky_orgsRETURN 'contract_concentration' AS pattern_id, c.cnpj AS cnpj, c.razao_social AS company_name, toFloat(size(risky_orgs)) AS risk_signal, sum(coalesce(risk_ct.value, 0.0)) AS amount_total
From public_pattern_contract_concentration.cypher - Threshold typically set at 0.5 (50%)
Detect companies with environmental embargoes still receiving contracts or loans:
MATCH (c:Company)WHERE elementId(c) = $company_idCALL { WITH c MATCH (c)-[:EMBARGADA]->(emb:Embargo) WHERE emb.date IS NOT NULL RETURN collect(DISTINCT emb.embargo_id) AS embargo_ids, min(emb.date) AS embargo_start}WITH c, embargo_ids, embargo_startWHERE size(embargo_ids) > 0CALL { WITH c, embargo_start OPTIONAL MATCH (c)-[:VENCEU]->(ct:Contract) WHERE ct.date >= embargo_start RETURN collect(DISTINCT ct.contract_id) AS contract_ids, sum(coalesce(ct.value, 0.0)) AS contract_total}CALL { WITH c, embargo_start OPTIONAL MATCH (c)-[:RECEBEU_EMPRESTIMO]->(loan:Finance) WHERE loan.date >= embargo_start RETURN collect(DISTINCT loan.finance_id) AS loan_ids, sum(coalesce(loan.value, 0.0)) AS loan_total}RETURN 'embargoed_receiving' AS pattern_id, c.cnpj AS cnpj, c.razao_social AS company_name, toFloat(size(embargo_ids) + size(contract_ids) + size(loan_ids)) AS risk_signal, coalesce(contract_total, 0.0) + coalesce(loan_total, 0.0) AS amount_total
MATCH (e)WHERE elementId(e) = $entity_idWITH eOPTIONAL MATCH (e)-[:SAME_AS*1..2]-(other)WITH e, collect(DISTINCT other) AS othersWITH [e] + others AS equivsUNWIND equivs AS eqMATCH (eq)-[r]-(n)WHERE type(r) <> 'SAME_AS' AND (n:Contract OR n:Sanction OR n:Amendment OR n:Election OR n:Finance OR n:Embargo OR n:Convenio)WITH DISTINCT n, labels(n) AS lbls, COALESCE(n.date, n.date_start, n.date_published, toString(n.year)) AS event_dateWHERE event_date IS NOT NULL AND event_date <> '' AND ($cursor IS NULL OR event_date < $cursor)RETURN elementId(n) AS id, event_date, lbls, properties(n) AS propsORDER BY event_date DESCLIMIT $limit
From entity_timeline.cypher - Supports cursor-based pagination and includes SAME_AS equivalents
Calculate exposure metrics aggregated across equivalent entities:
MATCH (e)WHERE elementId(e) = $entity_idWITH e, labels(e) AS lbls// Collect equivalent nodes via SAME_ASOPTIONAL MATCH (e)-[:SAME_AS*1..2]-(other)WITH e, lbls, collect(DISTINCT other) AS othersWITH e, lbls, [e] + others AS equivs// Count connectionsUNWIND equivs AS eqOPTIONAL MATCH (eq)-[r]-(connected) WHERE type(r) <> 'SAME_AS'WITH e, lbls, equivs, count(r) AS connection_count// Contract volumeUNWIND equivs AS eq2OPTIONAL MATCH (eq2)-[:VENCEU]->(c:Contract)WITH e, lbls, connection_count, COALESCE(sum(c.value), 0) AS contract_volume// Donation volumeUNWIND equivs AS eq3OPTIONAL MATCH (eq3)-[:DOOU]->(d)WITH e, lbls, connection_count, contract_volume, COALESCE(sum(d.valor), 0) AS donation_volume// Debt/loan volumeUNWIND equivs AS eq4OPTIONAL MATCH (eq4)-[:RECEBEU_EMPRESTIMO|DEVE]->(f:Finance)RETURN elementId(e) AS entity_id, lbls AS entity_labels, connection_count, contract_volume + donation_volume + COALESCE(sum(f.value), 0) AS financial_volume
From entity_score.cypher - Aggregates metrics across SAME_AS linked entities