Neo4j:Combine vários rótulos (2 ou mais)
Pergunta
Gostaria de fazer uma pesquisa e começar a percorrer a partir de 2 rótulos (condição OR).Por exemplo, preciso descobrir todos os nós que possuem rótulos 'Masculino' ou 'Feminino' e cuja propriedade, nome =~ '.tudo bem.'.
Solução
Você pode colocar isso no WHERE
cláusula:
MATCH n
WHERE n:Male OR n:Female
RETURN n
EDITAR
Como @tbaum aponta, isso desempenha um papel AllNodesScan
.Escrevi a resposta quando os rótulos eram relativamente novos e esperava que o planejador de consultas eventualmente a implementasse com um NodeByLabelScan
para cada etiqueta, como acontece com o caso de etiqueta única
MATCH n
WHERE n:Male
RETURN n
Ainda acho que esta é uma expressão razoável da consulta e que é razoável esperar que o planejador de consultas a implemente com varreduras de rótulos, mas a partir do Neo4j 2.2.3 a consulta ainda é implementada com um AllNodesScan
e um filtro de rótulo.Aqui está, portanto, uma alternativa mais detalhada.Como a disjunção do rótulo significa uma união de conjunto e essa união pode ser expressa de diferentes maneiras, podemos expressá-la de uma forma que o planejador de consulta implemente sem verificar todos os nós e, em vez disso, comece com um NodeByLabelScan
por rótulo.
MATCH (n:Male)
WHERE n.name =~ '.ail.'
RETURN n
UNION MATCH (n:Female)
WHERE n.name =~ '.ail.'
RETURN n
Isso significa expressar a consulta uma vez para cada rótulo e juntá-los com uma expressão explícita. UNION
.Isso não é irracional, pelo menos para um número menor de rótulos, mas não está claro para mim por que os planejadores de consulta não deveriam ser capazes de inferir a mesma implementação da consulta mais simples, então abri um problema no github aqui.
Outras dicas
MATCH n WHERE n:Label1 OR n:Label2
...resultará em um AllNodesScan, esta é uma má ideia!
talvez uma solução melhor:
OPTIONAL MATCH (n1:Label1)
WITH collect(distinct n1) as c1
OPTIONAL MATCH (n2:Label2)
WITH collect(distinct n2) + c1 as c2
OPTIONAL MATCH (n3:Label3)
WITH collect(distinct n3) + c2 as c3
UNWIND c3 as nodes
RETURN count(nodes),labels(nodes)
Com o Neo4j 3.4.7 o planejador de consultas faz um UNION e depois um DISTINCT de 2 NodeByLabelScan
s quando você entrega uma consulta WHERE com 2 filtros de rótulo OR.Tentando o banco de dados de vazamentos offshore sandbox com EXPLAIN MATCH (o) WHERE o:Officer OR o:Entity RETURN o
produz este planejamento:
A documentação da v3.0 diz o seguinte:
Também é possível descrever um nó que possui vários rótulos:
(a:User:Admin)-->(b)
Fonte: https://neo4j.com/docs/developer-manual/current/cypher/#_labels