2017-05-24 15 views
0

neo4jの絶対的なnoobであり、以前の質問で非常に寛大な助けを得ていたので、私はまだ苦労していると私はもう一度私の運を試すと思った。Neo4jの完全なパス数を返す

例のシナリオは、家に入って1つの部屋から別の部屋に歩く生徒のシナリオです。旅は、特定の部屋で開始または終了する必要はありませんが、学生が部屋に入る順序の順序が重要です。

私が知りたいことは、問題のパスが何回も取られたかを数えながら、学生が習得したすべての道筋です。以下のサンプルデータと私は(ブログ記事のシリーズと一緒に、前の質問の答えのおかげで)試したです:

ファイルdorm.csv

ID|SID|EID|ROOM|ENTERS|LEAVES 
1|1|12|BLUE|1/01/2015 11:00|4/01/2015 10:19 
2|2|18|GREEN|1/01/2015 12:11|1/01/2015 12:11 
3|2|18|YELLOW|1/01/2015 12:11|1/01/2015 12:20 
4|2|18|BLUE|1/01/2015 12:20|5/01/2015 10:48 
5|3|28|GREEN|1/01/2015 18:41|1/01/2015 18:41 
6|3|28|YELLOW|1/01/2015 18:41|1/01/2015 21:00 
7|3|28|BLUE|1/01/2015 21:00|9/01/2015 9:30 
8|4|36|BLUE|1/01/2015 19:30|3/01/2015 11:00 
9|5|40|GREEN|2/01/2015 19:08|2/01/2015 19:08 
10|5|40|ORANGE|2/01/2015 19:08|3/01/2015 2:43 
11|5|40|PURPLE|3/01/2015 2:43|4/01/2015 16:44 
12|6|48|GREEN|3/01/2015 11:52|3/01/2015 11:52 
13|6|48|YELLOW|3/01/2015 11:52|3/01/2015 17:45 
14|6|48|RED|3/01/2015 17:45|7/01/2015 10:00 

は、学生のためのノードを作成します、前の関係を作成ルームとログインが一意のIDプロパティで部屋に入る学生のイベントに識別される訪問

CREATE CONSTRAINT ON (student:Student) ASSERT student.studentID IS UNIQUE; 
CREATE CONSTRAINT ON (room:Room) ASSERT room.roomID IS UNIQUE; 
CREATE CONSTRAINT ON (visit:Visit) ASSERT visit.visitID IS UNIQUE; 


USING PERIODIC COMMIT 
LOAD CSV WITH HEADERS FROM "file:///dorm.csv" as line fieldterminator '|' 
MERGE (student:Student {studentID: line.SID}) 
MERGE (room:Room {roomID: line.ROOM}) 
MERGE (visit:Visit {visitID: line.ID, roomID: line.ROOM, studentID: line.SID, ticketID: line.EID}) 
create (student)-[:VERB]->(visit)-[:OBJECT]->(room) 

これは、ファイルdormprev内のデータを使用しています。学生がで走行する順序または配列決定することができます。 csv。学生が1つの部屋だけを訪問した場合、このIDは訪問/リンクのリンクを目的とするため、dormprevファイルには表示されません。

ID|PREV_ID|EID 
3|2|18 
4|3|18 
6|5|28 
7|6|28 
10|9|40 
11|10|40 
13|12|48 
14|13|48 

USING PERIODIC COMMIT 
LOAD CSV WITH HEADERS FROM "file:///dormprev.csv" as line fieldterminator '|' 
MATCH (new:Visit {visitID: line.ID}) 
MATCH (old:Visit {visitID: line.PREV_ID}) 
MERGE (new)-[:PREV]->(old) 

以下のように、私は以下のクエリ

MATCH (student:Student)-[:VERB]->(visit:Visit)-[:OBJECT]-(room:Room) 
RETURN student, visit, room 

により、すべての生徒の旅を見ることができるデータは、しかし、私は完全なパスに部屋のすべてを返す方法は考えています。

私はこのクエリ

MATCH p = (:Visit)<-[:PREV]-(:Visit) return p 

を実行する場合、私はそれは、例えば、別々のペアとして学生証2つのリターン緑と黄色、その後、イエローとブルーのためにことを見ることができます - 私は緑のように、そのを表示します

MATCH p = (:Visit)<-[:PREV]-(:Visit) 
WITH p, EXTRACT(v IN NODES(p) | v.roomID) AS rooms 
UNWIND rooms AS stays 
WITH p, COUNT(DISTINCT stays) AS distinct_stays 
WHERE distinct_stays = LENGTH(NODES(p)) 
RETURN EXTRACT(v in NODES(p) | v.roomID), count(p) 
ORDER BY count(p) DESC 

それはSENSを行う場合、それはむしろ「全体のパス」の数よりも、それらのペアの数を返します。、イエロー、ブルー

これはまた、私は以下のクエリを実行した場合ことを意味しe。

たとえば、SID 2とSID 3は、どちらもGREEN、YELLOW、BLUEの順にアクセスします。 SID 5は、緑色、オレンジ色、紫色の順に訪問します。

私が見ることを望んでいます:

[GREEN, YELLOW, BLUE] 2 
[GREEN, ORANGE, PURPLE] 1 

などは、上記のモデルとすることが可能であるので、誰が助けてくださいすることができた場合に正しい方向に私を指しますか?訪問された部屋の数は保証されておらず、1つから*まで何でもかまいません。しかし、1つの部屋しか訪れていないのであれば、それは本当に興味のあることではないので、このモデルが理にかなっていると思う理由もあります(再び、ブログのポストシリーズから盗まれました)。

上記が意味をなさないのですが、助けてくれれば幸いです。これは優れたユースケースであり、本当に便利です。

ご協力いただきありがとうございます。私はあなたが探していると思う何

答えて

0

は、可変経路長です。そして、これを照会の中で単に変更することによって達成できます(アスタリスクに注意してください)。

MATCH p = (:Visit)<-[:PREV*]-(:Visit) 

これ以上の発言をしてください。はい、訪問者ノードにroomIDとstudentIDを持たせることの利便性を理解しています(この特定のクエリはかなりシンプルです)。しかし、最初に関係を持つという点を無視しています(実際には、現時点では、実際にはStudentノードとRoomノードを持っていることに意味がありません)、あなたはそれらを維持するのに問題があります。

CREATE (student)-[:VERB]->(visit)<-[:OBJECT]-(room) 

その他:私たちはその後、訪問のための関係は、実際には次のように作成する必要があることわざの第三正規形の毛を;-)、分割しようとしている場合は第二に...(関係の方向に注意してください)それよりも、私はあなたが非常に高速な:-)にこのことができます

希望を移動していると言わなければならない、トムの提案のビットを構築トム

+0

感謝を!関係のポイントについては冗談があり、私は控えることで顕著な拘束を示しています;-)私は今のところ何かを追い求めていましたが、週末にこれを見たいと思っています。クエリを可変パス長に変更することについては、問題をほとんど解決するだろうと思うが、それはサブパスを含んでいないだろうが、私は "完全な"旅にしか興味がないだろうか?つまり、GYBではなく、[{G、Y}、{Y、B}、{GYB}]というクエリでG Y Bが実際に3回カウントされます。ありがとう。月曜日 – c95mbq

+0

を返信しますはい、間違いなく "関係のポイント"です:-)。とにかく、出発点に着信[:PREV]がなく、終了点に発信[:PREV]がないようにいくつかの追加要件を追加することもできます。そうすれば完全な旅しかできなくなります。 –

+0

私は物事を変更し、PREVではなくNEXTを作成しました。別のと一緒にあなたのコメントは、私は、少なくとも小さなサンプルデータと、期待される結果を返すように思われる以下のクエリをもたらし出会った投稿: 'MATCH P =(から:訪問) - [:NEXT *] - >(全訪問) ここでない((へ) - [:NEXT] - >()) なく(() - [:NEXT] - >()から)ノード内のp、EXTRACT(vで ( はPでとどまり、COUNT(DISTINCT滞在)distinct_stays distinct_stays = LENGTH(節(P)AS) RETURNエキスノード内の(V(P)AS部屋 UNWINDルームAS v.roomID)| | P)v.roomID )、count(p) ' ありがとうございました! – c95mbq

0

は、あなたが離れてやって代替モデルを検討するかもしれない:完全にノードを訪問し、そして作りますあなたの関係タイプは少し焦点が合っています:

(:Student)-[:VISITED]->(:Room) 

あなたは上で入力し、左のプロパティを設定することができます訪問したために:あなたが関係(客室と相当)を注文することができますVISITED関係、。

APOC Procedures(あなたのNeo4jバージョンに対応する正しいバージョンをインストールする必要があります)を使用して、日付文字列のタイムスタンプを解析するための代替インポートがあります。

USING PERIODIC COMMIT 
LOAD CSV WITH HEADERS FROM "file:///dorm.csv" as line fieldterminator '|' 
MERGE (student:Student {studentID: line.SID}) 
MERGE (room:Room {roomID: line.ROOM}) 
WITH student, room, apoc.date.parse(line.ENTERS, 'ms', 'MM/dd/yyyy HH:mm') as entered, apoc.date.parse(line.LEAVES, 'ms', 'MM/dd/yyyy HH:mm') as left 
CREATE (student)-[r:VISITED]->(room) 
SET r.entered = entered, r.left = left 

そして、すべてのパスとそれらのパスを取った学生の数を取得するために今、あなたのクエリが非常に容易になる:トム、感謝ヒープ

MATCH (s:Student)-[v:VISITED]->(r:Room) 
WHERE size((s)-[:VISITED]->()) > 1 
WITH s, r 
ORDER BY v.entered ASC 
WITH s, collect(r.roomID) as rooms 
RETURN rooms, count(s) 
+0

ご協力ありがとうございますInverseFalcon、非常に感謝します。私はこれをまだテストする機会がありませんでしたが、今後数日以内にそうしたいと考えており、返信します。あなたとあなたのトムの助けは、私のような奴隷にとって信じられないほど重要です。このような長い時間SQLを使って作業していましたが、私はこれについて頭を悩ませています。電球の瞬間を待ち望んでいます。永続する価値があるような否定できない価値だと思われています。そのような友好的で寛大な助けが長い道のりです。私はこれに戻るチャンスがあるとすぐに返信します。乾杯! – c95mbq

+0

助けてくれてうれしい!追加のリソースとアドバイスについては、[neo4j-users slack](https://neo4j.com/developer/slack/)を検討することもできます。また、neo4jブラウザ自体から提供される組み込みのチュートリアルのいくつかを確認してください。これらのチュートリアルはかなり豊富です! – InverseFalcon

+0

ありがとうInverseFalcon。私は余裕に登録して、それが大いに役立つことを確信しています。私はあなたの質問をテストすることができなかったので、私は間違ったバージョンのapocをつかんだと思うが、物事がちょっと消えてしまったときには必ずそれを再訪している。あなたやトムの答えを受け入れるかどうかを断言するが、トムと一緒に行った、私は両方を選ぶことができたらいい!すべてのお手伝いをありがとう、また、物事が静かなときにapocとあなたのソリューションを再訪します。 Cheers – c95mbq

関連する問題