LinkedIn でこの質問に対する回答を得ました:
https://www.linkedin.com/groups/Does-anybody-know-similarities-differences-2623939.S.5939804856381382658
以下の回答は、このクエリを参照しています。
MATCH (n:Asteroid) WHERE NOT n.name = 'Ceres' RETURN n LIMIT 25
答えは次のとおりです。
否定に関するあなたの質問には2つの答えがあります:
(i) プロパティ値の否定
これは上記のコメントで説明されているケースであり、本質的に正しいです。提供された例を再利用します。内部的には、「Asteroid」というラベルを持つすべてのノードが、ラベル インデックスを使用して取得されます。この後に「選択」演算子 (リレーショナル代数から) が続きます。これは、「name」プロパティを含まないか、「name」プロパティが「Ceres」ではないタプルのみを選択するために使用されます。その後、演算子が続きます。ご覧のとおり、これはリレーショナル データベースでの SQL の実行方法と変わりません。
(ii) パターン述語の否定
ここで、グラフ パターン マッチングが最大限に活用されます。
次のおもちゃのクエリがあるとします。このクエリでは、私が参加していないすべてのイベントを検索したいと考えています。
MATCH (me:Person {name: “me”}), (e:Event) WHERE NOT ( (me) - [:ATTENDED] -> (e) ) RETURN e
クエリ実行プランは演算子のツリーであり、それぞれに最大 2 つの子があります。
ツリーのルートには、'Anti Semi Apply' 演算子 (リレーショナル理論の anti-semijoin 演算子に相当) があります。左側の子は、タプルの 2 つのセットの直交積です。(1) ラベルとプロパティ インデックスを使用して取得された (me:Person {name: "me"}) に対応するノードのセット、および (2) セットラベル インデックスを使用して取得された、(e:Event) に対応するノードの数。デカルト積は、データベース内のすべての(e:Event) を持つ「me」ノードのすべての組み合わせで構成されることに注意してください。
デカルト積は一度に 1 つの行を発行し、この行 R は上向きに Anti Semi Apply オペレーターにパイプされます。次に、Anti Semi Apply は R を引数としてその右側の分岐にフィードし、R が右側の最終的な子孫として表示されるようにします。R は、すべての (me)-[:ATTENDED]-(some_e) 行を返す Expand 演算子に上方に渡されます (ここでの「me」は R のものと一致することに注意してください)。すぐに、そのような各行 S には、「some_e」を R の「e」に一致させるために、選択操作が適用されます。したがって、行 S は、事実上、「私」による「イベント」ATTEND です。次に、S は Anti Semi Apply にパイプされます。Rの行 S が見つからない場合、R が結果として返されます (これらはすべて「私」が参加していない「イベント」であるため)。
したがって、クエリに否定を含めることは、単純なフィルターとして扱われるのではなく、本質的にクエリ プラン全体に影響します。
Cypher の実行計画の詳細については、
http://neo4j.com/docs/snapshot/execution-plans.htmlを参照してください。