これは、フォローアップの質問です:私の前の質問でが最適化された方法で考慮にサイクルを取るためのNeo4jを依頼する方法
How to ask Neo4j to take cycles into account
、@ stdob--は親切に私は次のクエリを見つける助けました:
MATCH (n1:S)
OPTIONAL MATCH (n1)-[:R]->(n2:R)<-[:R]-(n3:E)
OPTIONAL MATCH (n3t)-[:R]->(n4:R:L)
WHERE n3t = n3
RETURN labels(n1), labels(n3t), labels(n4);
上記のクエリは次の代替です:
MATCH (n1:S)
OPTIONAL MATCH (n1)-[:R]->(n2:R)<-[:R]-(n3:E)-[:R]->(n4:R:L)
RETURN labels(n1), labels(n3t), labels(n4);
そして、最初のデータを使用しなければなりません。n2
とn4
が同じノードであり、Neo4jが同じノードを2回奪取することを拒否している可能性があるため、nullを返します。
最初のクエリは有効で機能していますが、パフォーマンスは非常に悪いです。これによりデータベースはデータ全体の検索を再開し、最後にn3t = n3
を使用して選択したノードと一致します。そのパフォーマンスがどれほど悪いかのヒントを与えるために、200kの大きさのデータセットでは、結果を返すのに5秒かかりますが、第2のOPTIONAL MATCH
とそのWHERE
を省略すると、結果は10ミリ秒未満で生成されますクエリ。誰もが興味を持っていた場合は、ここでは、クエリの実行プランです:
右の分岐が(私は二度目のノードを取るためのNeo4jを欺くしようとした)、私は前に述べた部分です。あなたが見ることができるように、Neo4jを2回目にノードにするために2Mのヒットが発生しました。この実行計画の実際のクエリは次のとおりです。
PROFILE MATCH (n5_1:Revision:`Account`)<-[:RevisionOf]-(n5_2:Entity:`Account`)
WITH n5_2, n5_1
ORDER BY n5_1.customer_number ASC
LIMIT 100
OPTIONAL MATCH (n5_1)-[:`Main Contact`]->(n4_1:Wrapper)<-[:Wrapper]-(:Revision:`Contact`)<-[:RevisionOf]-(n4_2:Entity:`Contact`)
OPTIONAL MATCH (n4_4)-[:RevisionOf]->(n4_3:Revision:Latest:`Contact`:Active)
WHERE (n4_2) = (n4_4)
RETURN n5_1, n5_2, n4_1, n4_2, n4_3
だから私の質問ですが、私はパフォーマンスつもり苦しむされていない状態のノードが二度目のために取られたサイファークエリを書くことができますか?
データとテストベッドの例については、他の質問に進んでください。
これについてカスタム手順を作成することを検討しましたか? APOCの[PathExplorer](https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3)のコードを調べるとよいでしょう。1/src/main/java/apoc/path/PathExplorer.java)を開始点として使用します。これにより、トラバーサルの一意性をより詳細に制御できるようになり、トラバーサル中にエッジを再利用できるようになります。 – InverseFalcon
あなたの最後のOPTIONAL MATCHはここでは新しい変数 'n4_4'を使用していますが、ちょっと奇妙ですが、' n4_2'と同じでなければならないと言った後にwhere節があります。このオプションのマッチがあなたのパフォーマンスヒットの原因です。代わりにこのマッチで 'n4_2'を使うとうまくいくはずです。しかし、あなたのリンクされた質問では、これはいくつかの望ましくない結果をもたらしましたが、 'n_43'がヌルでないことを確認する必要がある結果をフィルタリングするのは簡単であるようです。 – InverseFalcon