Skip to main content
A pergunta que aparece toda semana: “por que não acho isso?”. A resposta depende de que tipo de busca você quer, e são três coisas diferentes.

As três buscas


1. Achar pelo identificador

De graça: o próprio id_field

Um nó sem nenhum er_fields já é achável pelo valor da sua chave. A plataforma grava duas linhas no índice:
Então um Ticket com id_field: external_id e nada mais já responde a busca por 123145123.
Não declare er_fields só para isso — além de desnecessário, tira o nó do caminho de ingestão mais rápido.

Declarando: qualquer outra coluna

Para achar por uma coluna que não é a chave — o número do contrato quando a chave é id, o CPF, a placa — declare em er_fields:
Agora CT-2026-0001 acha o contrato.

Em qualquer formato

Os dois lados normalizam com a mesma regra, então o formato não importa:
A resposta vem com match_tier: identifier:<campo>, então você sabe por qual campo achou.

2. Achar todas que casam com um campo comum

cor, status, ano, modelo, faixa de valor. Isso não é identificador — não declare em er_fields, ou você funde tudo que compartilha o valor. Toda coluna em properties já está no nó do grafo. Então:
Funciona para qualquer propriedade, qualquer operador, e o resultado já vem filtrado por ACL. Não precisa declarar nada — a coluna estar em properties basta. O get_schema lista as propriedades reais de cada label, então dá para descobrir o que existe antes de filtrar.
Por que não pela busca de identificador? Porque o índice de identidade tem uma linha por chave: dois carros prata colidiriam. E porque essas duas perguntas são diferentes — uma resolve um valor em uma entidade, a outra filtra muitas.

Quando o grafo cresce: indexed_fields

Nada a declarar é verdade para o resultado. Não é verdade para o custo. Sem declarar nada, o MATCH (c:Carro) WHERE c.cor = 'prata'todo nó da label e descarta o que não casa — um NodeByLabelScan. Com 200 carros, ninguém percebe. Com 100 mil, percebe. Declarar a coluna como indexada faz o worker criar um índice de propriedade no grafo:
A mesma consulta passa a ser um NodeIndexSeek: o banco pula direto para os nós prata em vez de ler os 100 mil. Dá para conferir com EXPLAIN antes e depois — é a diferença entre as duas palavras no plano. Três coisas que precisam estar claras:
  • indexed_fields não é er_fields. Um acelera filtro, o outro declara identidade e funde entidades. Pôr cor em er_fields funde todos os carros prata numa entidade só.
  • indexed_fields não faz o search_entity achar “prata”. Ele acelera o Cypher. A caixa de busca continua sendo sobre identificadores.
  • Cada entrada é um índice a manter, com custo de escrita e de disco. Declare o que a operação filtra de verdade, não tudo que existe.
O get_schema informa ao agente quais propriedades estão indexadas — e ele descobre isso perguntando ao banco, não lendo a ontologia. Índice declarado mas nunca criado (porque o worker não rodou) simplesmente não aparece.

3. Achar por nome parecido

Cai nos tiers de texto: exato, depois trigrama, depois vetor. Nada a declarar — funciona sobre o nome que a plataforma derivou.

Como o rótulo é escolhido

Você não declara. A ordem é:
  1. um campo de nomename, nome, razao_social, title, full_name
  2. o primeiro er_field que tiver valor, na ordem que você declarou
  3. o id_field
Por isso er_fields: [placa, chassi, renavam] faz o carro aparecer como abc1d23 e não como 9BWZZZ377VT004251: você já disse qual identificador as pessoas usam. E-mail não conta como nome. Se for o melhor rótulo que a linha tem, ele chega lá pelo passo 2, por mérito próprio.

Tabela de decisão

Padrões e armadilhas

A regra de ouro, os erros que já aconteceram e o checklist antes do apply.

Escrevendo uma ontologia

Voltar à estrutura do arquivo, campo a campo.