2017-10-05 12 views
0

各ノードのノード間を通過した最小チェックポイントを検索しようとしています。各人が横断できる複数の経路があります。Cypherクエリを使用して最短部分パスを検索し、結果を集計します。

例:

CREATE 
    (:person {id: 0}), 
    (:person {id: 1})-[:rel1]->(:chkpt1 {id: '1'})-[:rel2]->(:chkpt2 {id: '2'}), 

    (:person {id: 2})-[:rel1]->(:chkpt1 {id: '1_1'}), 
    (:person {id: 2})-[:rel1]->(:chkpt1 {id: '1_2'})-[:rel2]->(:chkpt2 {id: '2_1'}), 
    (:person {id: 2})-[:rel1]->(:chkpt1 {id: '1_3'})-[:rel2]->(:chkpt2 {id: '2_2'})-[:rel3]->(:chkpt3 {id: '3_1'}), 

    (:person {id: 3})-[:rel1]->(:chkpt1 {id: '1_4'})-[:rel2]->(:chkpt2 {id: '2_3'})-[:rel3]->(:chkpt3 {id: '3_2'}), 
    (:person {id: 3})-[:rel1]->(:chkpt1 {id: '1_5'})-[:rel2]->(:chkpt2 {id: '2_4'})-[:rel3]->(:chkpt3 {id: '3_3'}), 
    (:person {id: 3})-[:rel1]->(:chkpt1 {id: '1_6'})-[:rel2]->(:chkpt2 {id: '2_5'})-[:rel3]->(:chkpt3 {id: '3_4'}) 

現在、私はOPTIONAL MATCH句を使用して、次のように複数のクエリを実行しています:

MATCH (p:person) 
OPTIONAL MATCH (p)-[:rel1]-(cp1:chkpt1) 
WITH p, cp1 
WHERE cp1 IS NULL 
RETURN p.id 

戻り値:

person0その後、私は見つけるために別のクエリを実行します次のチェックポイントに行かなかったすべての人。

MATCH (p:person)-[:rel1]-(cp1:chkpt1) 
OPTIONAL MATCH (cp1)-[:rel2]-(cp2:chkpt2) 
WITH p, cp1, cp2 
WHERE cp2 IS NULL 
RETURN DISTINCT p.id, cp1.id 

戻り値:PERSON2次のチェックポイントのために同様に

MATCH (p:person)-[:rel1]-(cp1:chkpt1)-[:rel2]-(cp2:chkpt2) 
OPTIONAL MATCH (cp2)-[:rel3]-(cp3:chkpt3) 
WITH p, cp1, cp2, cp3 
WHERE cp3 IS NULL 
RETURN DISTINCT p.id, cp1.id, cp2.id 

戻り値:PERSON1とPERSON2

私はPERSON2が前の横断を逃したとしてのみPERSON1返すようにしたいです。

MATCH (p:person)-[:rel1]-(cp1:chkpt1)-[:rel2]-(cp2:chkpt2)-[:rel3]-(cp3:chkpt3) 
RETURN DISTINCT p.id, cp1.id, cp2.id 

戻り値:PERSON2と

person3はしかし、私はPERSON2はそれがchkpt3とchkpt2することはなかったとしてだけでperson3返すようにしたいです。

すでに除外されている人は、別のトラバーサルで前回のチェックポイントに移っていないため、含めないでください。

例:

  • PERSON1のみ、彼らはそれをchkpt1することはなかったことを表示されるはずです。
  • person2はchkpt3にしなかったことを示すだけです。
  • person3は、最後のchkpt3へのすべてのパスを完了したので、chkpt3に表示されます。

特定のチェックポイントに設定した人の数を要約したいと思います。最短のチェックポイントにした複数の人がいるかもしれないので。

また、すべてのクエリを複数のOPTIONAL MATCH句と組み合わせようとしましたが、ノード数が増えると処理速度が大きく低下します。

合計ノード数は100,000〜100万になります。実際のトラバーサルは、人が何らかの値に基づいてフィルタリングされるため、1000sのノードしか含まない。

+0

これらのトレース(パス)はグラフに別々に保存されていますか?たとえば、person1のノードを2つ作成しますか? (あなたの最初のクエリがperson1を返すので、私はこれが当てはまると信じています) –

+1

各人物は複数のエッジを持つ単一のノードになります。 – JeffNewbie

+0

固定小額のチェックポイントがありますか?これも変更される可能性がありますか? –

答えて

0

ただし、人2はchkpt3とchkpt2にしなかったので、人3だけ返りたいです。

このクエリについてはどうですか?これは、人が関与するトラバーサルの数をカウントし、すべてのトラバーサルでチェックポイント3にしたかどうかをチェックします。

MATCH (p:person)-[r]-() 
WITH p, count(r) AS allTraversals 
MATCH (p)-[:rel1]-(cp1:chkpt1)-[:rel2]-(cp2:chkpt2)-[:rel3]-(cp3:chkpt3) 
WITH p, allTraversals, count(cp3) AS cp3s 
WHERE allTraversals = cp3s 
RETURN p 

(注:これはperson0のために動作しません。)

また、観測のカップルは:

(1)あなたはより多くの負の条件を策定するWHERE NOT <pattern>構文を使用することができます簡潔な方法。

MATCH (p:person) 
WHERE NOT (p:person)-[:rel1]->(:chkpt1) 
RETURN p 

それが可能だ場合は(2)、あなたは、単一のノードとして、データモデルと店舗名とチェックポイントの見直しを検討し、それらの間のパスを追加することがあります。これはよりグラフに似た表現であり、効率的なクエリを作成するのに役立ちます。

+0

ご回答いただきありがとうございます。質問を更新しました。 (1)私はそれを試します (3)到達した最も早いチェックポイントを探しているので、人1はchkpt1に到達していないと表示されます。 人2については、明確にするために質問を更新しました。 私はどれくらい多くの人がすべてのchkptsにそれを作ったのかを調べたいと思っています。 – JeffNewbie

関連する問題