2017-02-18 6 views
1

これは、フォローアップの質問です:私の前の質問でが最適化された方法で考慮にサイクルを取るための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); 

そして、最初のデータを使用しなければなりません。n2n4が同じノードであり、Neo4jが同じノードを2回奪取することを拒否している可能性があるため、nullを返します。

最初のクエリは有効で機能していますが、パフォーマンスは非常に悪いです。これによりデータベースはデータ全体の検索を再開し、最後にn3t = n3を使用して選択したノードと一致します。そのパフォーマンスがどれほど悪いかのヒントを与えるために、200kの大きさのデータセットでは、結果を返すのに5秒かかりますが、第2のOPTIONAL MATCHとそのWHEREを省略すると、結果は10ミリ秒未満で生成されますクエリ。誰もが興味を持っていた場合は、ここでは、クエリの実行プランです:

enter image description here

右の分岐が(私は二度目のノードを取るための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 

だから私の質問ですが、私はパフォーマンスつもり苦しむされていない状態のノードが二度目のために取られたサイファークエリを書くことができますか?

データとテストベッドの例については、他の質問に進んでください。

+1

これについてカスタム手順を作成することを検討しましたか? APOCの[PathExplorer](https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3)のコードを調べるとよいでしょう。1/src/main/java/apoc/path/PathExplorer.java)を開始点として使用します。これにより、トラバーサルの一意性をより詳細に制御できるようになり、トラバーサル中にエッジを再利用できるようになります。 – InverseFalcon

+0

あなたの最後のOPTIONAL MATCHはここでは新しい変数 'n4_4'を使用していますが、ちょっと奇妙ですが、' n4_2'と同じでなければならないと言った後にwhere節があります。このオプションのマッチがあなたのパフォーマンスヒットの原因です。代わりにこのマッチで 'n4_2'を使うとうまくいくはずです。しかし、あなたのリンクされた質問では、これはいくつかの望ましくない結果をもたらしましたが、 'n_43'がヌルでないことを確認する必要がある結果をフィルタリングするのは簡単であるようです。 – InverseFalcon

答えて

1

。それはあなたが探しているもの収まる場合は、このクエリは同じアプローチを使用し、この質問のための解決策になる可能性がありますパフォーマンスの問題を解決する必要があり

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`) 
WHERE (n4_2)-[:RevisionOf]->(:Revision:Latest:`Contact`:Active) 
OPTIONAL MATCH (n4_2)-[:RevisionOf]->(n4_3:Revision:Latest:`Contact`:Active) 
RETURN n5_1, n5_2, n4_1, n4_2, n4_3 

これは続けて、あなたの最後のオプションMATCHでn4_2、あなた観察された。

あなたが以前の質問で指摘したように、最初のOPTIONAL MATCHが成功する状況を避けたいが、2番目のものが失敗し、変数を最初のOPTIONAL MATCH 。

最初のOPTIONAL MATCHの後にWHEREを追加して、2番目のOPTIONAL MATCHで探しているパターンが最後のノードから外れている場合にのみ一致を強制します(このような場合でも機能します)。パターンは、OPTIONAL MATCHからのリレーションシップとノードを再利用します)。

+0

ありがとう、このソリューションは完璧です。 – Mehran

+0

それを聞いてうれしい!あなたがチャンスを得たら、この答えを受け入れることができますか? – InverseFalcon

+0

申し訳ありませんが私はやったと思った – Mehran

1

あなたは別途に尾を収集してみてください。私はあなたのリンクの質問にあなたが説明した結果表を与えるべきである答えを掲載

PROFILE 
MATCH (n1:S) 
OPTIONAL MATCH (n1)-[:R]->(n2:R)<-[:R]-(n3:E) 
WITH n1, [null] + ((n3)-[:R]->(:R:L)) as tail 
WITH n1, tail, size(tail) as tailSize 
UNWIND tail as t 
WITH n1, tailSize, t WHERE (tailSize = 2 AND NOT t is NULL) OR tailSize = 1 
WITH n1, nodes(t) as nds 
WITH n1, nds[0] as n3t, nds[1] as n4 
RETURN labels(n1), labels(n3t), labels(n4) 
関連する問題