I want to Traverse a PATH in neo4j (preferably using Cypher, but I can write neo4j managed extensions).
Problem - For any starting node (:Person) I want to traverse hierarchy like
(me:Person)-[:FRIEND|:KNOWS*]->(newPerson:Person)
if the :FRIEND outgoing relationship is present then the path should traverse that, and ignore any :KNOWS outgoing relationships, if :FRIEND relationship does not exist but :KNOWS relationship is present then the PATH should traverse that node.
Right now the problem with above syntax is that it returns both the paths with :FRIEND and :KNOWS - I am not able to filter out a specific direction based on above requirement.
For the ease of possible further answers and solutions I note my graph creating statement:
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;
If you do not need every path to all nodes of the entire path, but only the whole, I recommend using shortestPath() for performance reasons.
Note the missing node 'Person J', because it owns a FRIENDS
relationship to node 'Person I'.
Alternatively you could use the Expand paths functions of the APOC user library . Depending on the next steps of your process you can choose between the identification of nodes, relationships or both.
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;
startNode
following the given relationships ( relationshipFilter: 'FRIEND>'
) adhering to the label filter ( labelFilter: '+Person'
). startNode
following the given relationships ( relationshipFilter: 'KNOWS>'
) adhering to the label filter ( labelFilter: '+Person'
). FRIEND
relationship type (omit the .name
part if you need the complete node) KNOWS
relationship type (omit the .name
part if you need the complete node) ╒═════════════════════════════════════════════╤═════════════════════════════════════════════╕
│"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
This is a matter of interrogating the types of outgoing relationships for each node and then making a prioritized decision on which relationships to retain leveraging some nested case logic.
Using the small graph above
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
I believe this returns your expected result:
Based on your logic, there should be no traversal to Person G or Person H from Person A, as there is a FRIEND relationship from Person A to Person B that takes precedence.
However there is a traversal from Person H to Person I because of the existence of the singular KNOWS relationship, and then a subsequent traversal from Person I to Person J.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.