簡體   English   中英

有沒有辦法使用Cypher遍歷neo4j Path以獲得不同的關系

[英]Is there a way to Traverse neo4j Path using Cypher for different relationships

我想在neo4j中遍歷PATH(最好使用Cypher,但我可以編寫neo4j托管擴展)。

問題 - 對於任何起始節點(:Person),我想遍歷層次結構,如

(我:人) - [:朋友|:KNOWS *] - >(newPerson:人)

如果:FRIEND傳出關系存在,那么路徑應該遍歷那個,並忽略任何:KNOWS傳出關系,如果:FRIEND關系不存在但是:KNOWS關系存在,那么PATH應該遍歷該節點。

現在上面語法的問題是它返回兩個路徑:FRIEND和:KNOWS - 我無法根據上述要求過濾掉特定方向。

1.示例數據集

為了便於進一步解答和解決方案,我注意到我的圖表創建語句:

CREATE
  (personA:Person {name:'Person A'})-[:FRIEND]->(personB:Person {name: 'Person B'}),
  (personB)-[:FRIEND]->(personC:Person {name: 'Person C'}),
  (personC)-[:FRIEND]->(personD:Person {name: 'Person D'}),
  (personC)-[:FRIEND]->(personE:Person {name: 'Person E'}),
  (personE)-[:FRIEND]->(personF:Person {name: 'Person F'}),
  (personA)-[:KNOWS]->(personG:Person {name: 'Person G'}),
  (personA)-[:KNOWS]->(personH:Person {name: 'Person H'}),
  (personH)-[:KNOWS]->(personI:Person {name: 'Person I'}),
  (personI)-[:FRIEND]->(personJ:Person {name: 'Person J'});

圖1

2.場景“可選匹配”

2.1解決方案

MATCH (startNode:Person {name:'Person A'})
OPTIONAL MATCH friendPath = (startNode)-[:FRIEND*]->(:Person)
OPTIONAL MATCH knowsPath = (startNode)-[:KNOWS*]->(:Person)
RETURN friendPath, knowsPath;

如果您不需要遍歷整個路徑的所有節點的每條路徑,而只需要整個路徑,我建議使用shortestPath()以提高性能。

2.1結果

注意缺少的節點'Person J',因為它擁有與節點'Person I'的FRIENDS關系。

圖2

3.場景“展開路徑”

3.1解決方案

或者,您可以使用APOC用戶庫的“ 擴展路徑”功能。 根據流程的后續步驟,您可以選擇節點,關系或兩者的標識。

MATCH (startNode:Person {name:'Person A'})
CALL apoc.path.subgraphNodes(startNode,
  {maxLevel: -1, relationshipFilter: 'FRIEND>', labelFilter: '+Person'}) YIELD node AS friendNodes
CALL apoc.path.subgraphNodes(startNode,
  {maxLevel: -1, relationshipFilter: 'KNOWS>', labelFilter: '+Person'}) YIELD node AS knowsNodes
WITH
  collect(DISTINCT friendNodes.name) AS friendNodes,
  collect(DISTINCT knowsNodes.name) AS knowsNodes
RETURN friendNodes, knowsNodes;

3.2解釋

  • 第1行:根據名稱定義起始節點
  • 第2-3行:在給定的關系( relationshipFilter: 'FRIEND>' )之后從給定的startNode擴展,粘貼到標簽過濾器( labelFilter: '+Person' )。
  • 第4-5行:在給定的關系( relationshipFilter: 'KNOWS>' )之后從給定的startNode擴展,粘貼到標簽過濾器( labelFilter: '+Person' )。
  • 第7行:按照FRIEND關系類型聚合所有節點(如果需要完整節點,則省略.name部分)
  • 第8行:按照KNOWS關系類型聚合所有節點(如果需要完整節點,則省略.name部分)
  • 第9行:渲染結果節點組

3.3結果

╒═════════════════════════════════════════════╤═════════════════════════════════════════════╕
│"friendNodes"                                │"knowsNodes"                                 │
╞═════════════════════════════════════════════╪═════════════════════════════════════════════╡
│["Person A","Person B","Person C","Person E",│["Person A","Person H","Person G","Person I"]│
│"Person D","Person F"]                       │                                             │
└─────────────────────────────────────────────┴─────────────────────────────────────────────┘
MATCH p = (me:Person)-[:FRIEND|:KNOWS*]->(newPerson:Person) 
WITH p, extract(r in relationships(p) | type(r)) AS types
RETURN p ORDER BY types asc LIMIT 1

這是詢問每個節點的傳出關系的類型,然后對哪些關系保留利用某些嵌套的案例邏輯做出優先級決定的問題。

使用上面的小圖

MATCH path = (a)-[r:KNOWS|FRIEND]->(b) WITH a, COLLECT([type(r),a,r,b]) AS rels WITH a, rels, CASE WHEN filter(el in rels WHERE el[0] = "FRIEND") THEN filter(el in rels WHERE el[0] = "FRIEND") ELSE CASE WHEN filter(el in rels WHERE el[0] = "KNOWS") THEN filter(el in rels WHERE el[0] = "KNOWS") ELSE [''] END END AS search UNWIND search AS s RETURN s[1] AS a, s[2] AS r, s[3] AS b

我相信這會返回您的預期結果:

在此輸入圖像描述

根據您的邏輯,不應該從人員A遍歷人員G或人員H,因為從人員A到人員B的FRIEND關系優先。

然而,由於存在單一的KNOWS關系,然后隨后從人I到人J的遍歷,從人H到人I的遍歷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM