2017-02-24 12 views
0

Nノードをそれぞれの間に逐次関係で作成したいと思います。Neo4jには、1つのサイファークエリで可変数の関係を作成する方法がありますか?

私の要件は、ユーザーのワークフローを作成することです。 UIの最後では、互いに関連していなければならないjsonオブジェクトの配列を送信できます。たとえば、次のように

{steps: [ {name: 'step 1'}, {name: 'step2'}, {name: 'step3'}] }

私は上記のJSONから希望する3つのノードを作成することで、それらを順番にリンクされている

(step 1)-[:has_next_step]->(step 2)-[:has_next_step]->(step 3)

はこれを行う簡単な方法はありますか?私の例は3つのノードを持っていることを覚えておいてください。実際には、5-15ステップのどこかにあるので、サイファークエリはこの変数入力を処理できる必要があります。私は入力を制御することもできることに注意してください。もっと簡単なjson params変数があれば、それを使うこともできます。

答えて

2

あなたが直面する唯一の問題は、ステップのコレクションを反復するときに、コレクション内の要素を表すノードを認識できなくなることです。

ので、ハッキングのビット、あなたが識別子として機能するクエリの先頭にタイムスタンプを使用することができます。

WITH {steps: [ {name: 'step 1'}, {name: 'step2'}, {name: 'step3'}] } AS object 
WITH object.steps AS steps, timestamp() AS identifier 
UNWIND range(1, size(steps)-1) AS i 
MERGE (s:Step {id: identifier + "_" + (i-1)}) SET s.name = (steps[i-1]).name 
MERGE (s2:Step {id: identifier + "_" + (i)}) SET s2.name = (steps[i]).name 
MERGE (s)-[:NEXT]->(s2) 

説明:

私はUNWINDとステップのコレクションを反復処理し、ためには、既に反復されたステップを表す各ノードを認識するために、トランザクションのタイムスタンプであるダミー識別子+「_」+シーケンスカーソルを使用します。

大規模では、独自の識別子(クライアントサイドで生成されたuuidなど)を使用し、その上にインデックス/ユニーク制約がある方がよいでしょう。

enter image description here

より高度:

あなたはユーザーノードを持っており、それにステップを添付する(文脈:ユーザーは、前にそれに接続されている任意の段階だったしませんでした)

を作成します。ダミーユーザー:

CREATE (u:User {login:"me"}) 

手順のリストを作成し、ユーザーに添付

WITH {steps: [ {name: 'step 1'}, {name: 'step2'}, {name: 'step3'}] } AS object 
WITH object.steps AS steps, timestamp() AS identifier 
UNWIND range(1, size(steps)-1) AS i 
MERGE (s:Step {id: identifier + "_" + (i-1)}) SET s.name = (steps[i-1]).name 
MERGE (s2:Step {id: identifier + "_" + (i)}) SET s2.name = (steps[i]).name 
MERGE (s)-[:NEXT]->(s2) 
WITH identifier + "_" + (size(steps)-1) AS lastStepId, identifier + "_0" AS firstStepId 
MATCH (user:User {login:"me"}) 
OPTIONAL MATCH (user)-[r:LAST_STEP]->(oldStep) 
DELETE r 
WITH firstStepId, lastStepId, oldStep, user 
MATCH (s:Step {id: firstStepId}) 
MATCH (s2:Step {id: lastStepId}) 
MERGE (user)-[:LAST_STEP]->(s) 
WITH s2, collect(oldStep) AS old 
FOREACH (x IN old | MERGE (s2)-[:NEXT]->(x)) 

enter image description here

コンテキスト、(同じクエリを実行しますが、視覚的に差分を参照する手順については、異なる名前を持つ):ユーザーが彼に添付すでにステップがあります。

WITH {steps: [ {name: 'second 1'}, {name: 'second 2'}, {name: 'second 3'}] } AS object 
WITH object.steps AS steps, timestamp() AS identifier 
UNWIND range(1, size(steps)-1) AS i 
MERGE (s:Step {id: identifier + "_" + (i-1)}) SET s.name = (steps[i-1]).name 
MERGE (s2:Step {id: identifier + "_" + (i)}) SET s2.name = (steps[i]).name 
MERGE (s)-[:NEXT]->(s2) 
WITH identifier + "_" + (size(steps)-1) AS lastStepId, identifier + "_0" AS firstStepId 
MATCH (user:User {login:"me"}) 
OPTIONAL MATCH (user)-[r:LAST_STEP]->(oldStep) 
DELETE r 
WITH firstStepId, lastStepId, oldStep, user 
MATCH (s:Step {id: firstStepId}) 
MATCH (s2:Step {id: lastStepId}) 
MERGE (user)-[:LAST_STEP]->(s) 
WITH s2, collect(oldStep) AS old 
FOREACH (x IN old | MERGE (s2)-[:NEXT]->(x)) 

enter image description here

+1

もしあなたがapocを持っていれば、 'apoc.nodes.link(nodes、" NEXT ")' –

+0

を使うことができます。私は人々がAPOCの前にCypherを学ぶことを好むですが、そうです!APOC FTW! –

+1

@ChristopheWillemsenありがとう、私はuuidを持っていますが、ただ例を挙げていました。これは完璧に機能し、APOCが必要な時にはAPOCを調べます。ありがとう! –

2

いくつかのAPOC手順を使用してノードを作成し、それらをリンクすることができます。

  • apoc.create.nodesは、同じラベルを持つ複数のノードを作成するために使用できます。
  • apoc.nodes.linkを使用して、同じタイプの関係でノードを連鎖させることができます。たとえば、

、以下のクエリは、(Stepラベルで)あなたの3のサンプルノードを作成し、その後順に、それらを一緒にリンクし、has_next_step関係で:

CALL apoc.create.nodes(['Step'],[{name:'step1'},{name:'step2'},{name: 'step3'}]) YIELD node 
WITH COLLECT(node) AS nodes 
CALL apoc.nodes.link(nodes, 'has_next_step') 
RETURN SIZE(nodes) 

apoc.nodes.link手順は戻りません。何もないので、上記のクエリは、作成されて一緒にリンクされたノードの数を返します。

関連する問題