[英]Neo4j - Using Cypher start at a node and Traverse graph to a specified depth and find nodes and relationships
[英]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 - 我無法根據上述要求過濾掉特定方向。
為了便於進一步解答和解決方案,我注意到我的圖表創建語句:
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'});
MATCH (startNode:Person {name:'Person A'})
OPTIONAL MATCH friendPath = (startNode)-[:FRIEND*]->(:Person)
OPTIONAL MATCH knowsPath = (startNode)-[:KNOWS*]->(:Person)
RETURN friendPath, knowsPath;
如果您不需要遍歷整個路徑的所有節點的每條路徑,而只需要整個路徑,我建議使用shortestPath()以提高性能。
注意缺少的節點'Person J',因為它擁有與節點'Person I'的FRIENDS
關系。
或者,您可以使用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;
relationshipFilter: 'FRIEND>'
)之后從給定的startNode
擴展,粘貼到標簽過濾器( labelFilter: '+Person'
)。 relationshipFilter: 'KNOWS>'
)之后從給定的startNode
擴展,粘貼到標簽過濾器( labelFilter: '+Person'
)。 FRIEND
關系類型聚合所有節點(如果需要完整節點,則省略.name
部分) KNOWS
關系類型聚合所有節點(如果需要完整節點,則省略.name
部分) ╒═════════════════════════════════════════════╤═════════════════════════════════════════════╕
│"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.