I want to get all paths between two nodes so that at least one node from a list of nodes exists in those paths.
how can I do this using cypher ?
Assuming you have provided your list of nodes as a cypher collection, would this do the job?
MATCH path=(start)-[r:*1..100]-(end)
WHERE ANY(node_on_path in NODES(path)
WHERE node_on_path IN node_collection)
You may also try using a list of values against which the nodes on the path are checked, something like
MATCH path=(start)-[r:1..100]-(end)
WHERE ANY(node_on_path in NODES(path)
WHERE node_on_path.some_property IN list_of_acceptable_values)
Related
Having this query working in Cypher (Neo4j):
MATCH p=(g:Node)-[:FOLLOWED_BY *2..2]->(g2:Node)
WHERE g.group=10 AND g2.group=10
RETURN p
which returns all possible paths belonging a specific group (group is just a property to classify nodes), I am struggling to get a query that returns the paths in common between both collection of paths. It would be something like this:
MATCH p=(g:Node)-[:FOLLOWED_BY *2..2]->(g2:Node)
WHERE g.group=10 AND g2.group=10
MATCH p=(g3:Node)-[:FOLLOWED_BY *2..2]->(g4:Node)
WHERE g3.group=15 AND g4.group=15
RETURN INTERSECTION(path1, path2)
Of course I made that up. The goal is to get all the paths in common between both queries.
The start/end nodes of your 2 MATCHes have different groups, so they can never find common paths.
Therefore, when you ask for "paths in common", I assume you actually want to find the shared middle nodes (between the 2 sets of 3-node paths). If so, this query should work:
MATCH p1=(g:Node)-[:FOLLOWED_BY *2]->(g2:Node)
WHERE g.group=10 AND g2.group=10
WITH COLLECT(DISTINCT NODES(p1)[1]) AS middle1
MATCH p2=(g3:Node)-[:FOLLOWED_BY *2]->(g4:Node)
WHERE g3.group=15 AND g4.group=15 AND NODES(p2)[1] IN middle1
RETURN DISTINCT NODES(p2)[1] AS common_middle_node;
In my flight modelization, I would like to search for path with 1 stop which is equivalent in the graph to have a 4 hops relationships from the source to the destination. When searching the path with :
match (s:Airport{airportName:'CAN'}),
(d:Airport{airportName:'ICN'})
with s,d
match p = (s)<-[*4]->(d)
return nodes(p), relationships(p)
But this also give me path with airport node that are visited twice, like this : airport node
So my question is, how to exclude paths which contains duplicated nodes ?
How to detect whether there is a duplicated node within a path ?
Thank you !
If you have access to APOC Procedures, you can try using apoc.algo.allSimplePaths(), which will not contain any loops back to a previously visited node in the path.
match (s:Airport{airportName:'CAN'}),
(d:Airport{airportName:'ICN'})
call apoc.algo.allSimplePaths(s, d, '', 4) yield path
return nodes(path), relationships(path)
I am trying to figure out how to write a Cypher query for Neo4J. I have a linked list of nodes like this:
n-[FIRST_NODE]->n-[NEXT_NODE]->n-[NEXT_NODE]->.....
The FIRST_NODE relationship has a property that says how deep in the list we should retrieve nodes. I want to retrieve a list of nodes possibly skipping one based on a property in n and retrieve x amount of nodes where x is the depth we should traverse in the list. Does this make sense?
I have come up with the below query but it doesn't work!
MATCH (x)-[firstIssue:FIRST_NODE]->(y:Type1)
MATCH (z)-[:NEXT_NODE*1..{firstIssue.Count}]->(a:Type1)
RETURN x,y,z,a
Any help would be apprectiated!.
Cypher does not support dynamic bounds for variable length paths.
However, in neo4j 3.x, you can install the APOC plugin and use the apoc.path.expand procedure. For example:
MATCH (x)-[firstIssue:FIRST_NODE]->(y:Type1)
CALL apoc.path.expand(y, 'NEXT_NODE>', '+Type1', 1, firstIssue.Count) YIELD path
RETURN x, firstIssue, path;
Do you know how to write a cypher query that would return all the transitive relationships related to a node.
For instance if I have : (node1)-[rel1]->(node2)-[rel2]->(node3).
I'd like a query that, given node1 returns rel1 and rel2.
Thanks for your help !
You need to use a variable path match, assuming your start node is node 1 having label Label and name='node1':
MATCH path=(node1:Label {name:'node1'})-[*..100]->()
RETURN relationships(path) as rels
The relationships function returns a list holding all relationships along that path. It is a best practice to provide an upper limit to variable depth matches, here I've set it arbitrarily to 100.
update regarding comment below
To get the id's of the relationships:
MATCH path=(node1:Label {name:'node1'})-[*..100]->()
RETURN [r in relationships(path) | ID(x)] as relIds
I have the following node structure Emp[e_id, e_name, e_bossid]. What is more I have a recursive query that exploit the database in recursive traversal on SELF relation e_bossid-[REPORTS_TO]->e_id
MATCH (e:Employee) WHERE NOT (e)-[:REPORTS_TO]->()
SET e:Root;
MATCH path = (b:Root)<-[:REPORTS_TO*]-(e:Employee)
RETURN path
limit 1000;
However the result is PATH. I would like to have result in form of NODES not the path. I tried to use the nodes(path), but it gives me an error:
org.codehaus.jackson.map.JsonMappingException: Reference node not available (through reference chain: java.util.ArrayList[0]->java.util.HashMap["rel"]->java.util.HashMap["nodes(path)"]->java.util.ArrayList[0]->org.neo4j.rest.graphdb.entity.RestNode["restApi"]->org.neo4j.rest.graphdb.RestAPIFacade["direct"]->org.neo4j.rest.graphdb.ExecutingRestAPI["referenceNode"])
When I query without nodes(path) it seems to return only paths.
How this should be done on the ground of cypher query?
I'm not sure why you would want to get all possible paths in your organizational hierarchy. Maybe what you want to get is a set of paths from the leaves of the tree to the root of the tree, and to return each unique set as a row of nodes.
MATCH (b:Employee)
WHERE NOT (b)-[:REPORTS_TO]->()
MATCH (l:Employee)
WHERE NOT (l)<-[:REPORTS_TO]-()
MATCH p = shortestPath((b)<-[:REPORTS_TO*]-(l))
RETURN nodes(p) as reports
As far as your error goes, that looks like a bug, although I don't know what version of Neo4j you are using. In all likelihood, your query won't complete because your Root employees are still a member of the Employee label. Which means that this pattern: MATCH path = (b:Root)<-[:REPORTS_TO*]-(e:Employee) matches the Root employees on each side of the variable length traversal.
Give my query a try and let me know what happens.