web-dev-qa-db-ja.com

Neo4j:複数のラベルに一致(2つ以上)

検索を行いたいのですが、2つのラベル(OR条件)からトラバースを開始したいと思います。たとえば、ラベルが 'Male'または 'Female'で、そのプロパティがname =〜 '.ail。'であるすべてのノードを見つける必要があります。

42

それをWHERE句に入れることができます:

MATCH n
WHERE n:Male OR n:Female
RETURN n

[〜#〜] edit [〜#〜]

@tbaumが指摘しているように、これはAllNodesScanを実行します。ラベルがかなり新しいときに答えを書き、クエリプランナーが最終的に各ラベルにNodeByLabelScanを使用して実装することを期待しました。

MATCH n
WHERE n:Male
RETURN n

私はまだこれがクエリの合理的な表現であり、クエリプランナがラベルスキャンで実装することを期待するのが合理的であると思いますが、Neo4j 2.2.3の時点でクエリはAllNodesScanとラベルフィルター。したがって、これはより冗長な代替案です。ラベルの選言は集合の集合を意味し、この集合はさまざまな方法で表現できるため、クエリプランナーがすべてのノードをスキャンせずに実装し、代わりにラベルごとにNodeByLabelScanで始まるように表現できます。

MATCH (n:Male)
WHERE n.name =~ '.ail.'
RETURN n
UNION MATCH (n:Female)
WHERE n.name =~ '.ail.'
RETURN n

つまり、ラベルごとにクエリを1回表現し、明示的なUNIONで結合します。少なくともラベルの数が少ない場合、これは不合理ではありませんが、クエリプランナーが単純なクエリから同じ実装を推論できない理由が明確ではないため、github問題を開きました ここ

46
jjaderberg
MATCH n WHERE n:Label1 OR n:Label2

... AllNodesScanになりますが、これは悪い考えです!

おそらくより良い解決策:

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) 
14
tbaum

Neo4j 3.4.7では、クエリプランナーは、2つのORされたラベルフィルターを使用してWHEREクエリを渡すと、UNIONを実行し、次に2 NodeByLabelScansのDISTINCTを実行します。 sandbox Offshore Leaks Database with EXPLAIN MATCH (o) WHERE o:Officer OR o:Entity RETURN oを試すと、次の計画が得られます。

Neo4j query planning

2
Markus Döring