Reputation: 3
i'm new to neo4j.
I created this example:
// (Node2)
// / \
// Rel2 / \ Rel3
// / \
// (Node1) ------> (Node3)
// Rel1
//
// create nodes
CREATE
(n1:Node1{id:1,rights:["admin","user"]}),
(n2:Node2{id:2,rights:["admin","user"]}),
(n3:Node3{id:3,rights:["admin","user"]})
// create relationships
CREATE (n1)-[r1:Rel1{id:11,rights:["admin"]}]->(n3)
CREATE (n1)-[r2:Rel2{id:12,rights:["admin","user"]}]->(n2)
CREATE (n2)-[r3:Rel3{id:13,rights:["admin","user"]}]->(n3)
RETURN n1,n2,n3,r1,r2,r3
Each node and relationship has a property array with some rights values. I want to create a query that gives me (shortest) paths between two nodes with specified properties. Example:
User has rights 'admin', the path should be:
(Node1)-[Rel1]->(Node3)
(Each node and releationship has the 'admin' String in the 'rights' property.)
If the user has the right 'user', the path should be:
(Node1)-[Rel2]-(Node2)-[Rel3]-(Node3)
(Because the Rel1 relation didn't have the 'user' String in the 'rights' property.)
At first i tried this query that worked:
WITH ["admin","otherRight"] AS usersRights
MATCH path=allShortestPaths((n1:Node1{id:1})-[*..4]-(n2:Node3{id:3}))
WITH *, relationships(path) AS rels, nodes(path) as nodes
WHERE ANY (rel IN rels WHERE ANY(r IN rel.rights WHERE r IN usersRights))
AND ANY (node IN nodes WHERE ANY(r IN node.rights WHERE r IN usersRights))
RETURN path
Then i replaced the 'admin' with 'user', but this query didn't work (has no rusults):
WITH ["user","otherRight"] AS usersRights
MATCH ... // same as above
...
RETURN path
The follwing query matches my needed result, but in this case, i would have to make several queries to get the desired result (shortest paths) for depth n.
WITH ["user","otherRight"] AS usersRights
MATCH path=(n1:Node1{id:1})-[r1]-(n2)-[r2]-(n3:Node3{id:3})
WHERE ANY(r IN n1.rights WHERE r IN usersRights)
AND ANY(r IN r1.rights WHERE r IN usersRights)
AND ANY(r IN n2.rights WHERE r IN usersRights)
AND ANY(r IN r2.rights WHERE r IN usersRights)
AND ANY(r IN n3.rights WHERE r IN usersRights)
RETURN path
Is it possible to create a cypher query that gives me the disired results ?
Thanks.
Upvotes: 0
Views: 686
Reputation: 67044
Your first query has a WITH
clause separating the MATCH
and WHERE
clauses, which prevents the WHERE
clause from affecting the behavior of the allshortestpath()
function. Therefore, the function was just returning the shortest path(s) without testing the nodes and relationships.
Try this, instead:
WITH ["admin","otherRight"] AS usersRights
MATCH path=allShortestPaths((n1:Node1{id:1})-[*..4]-(n2:Node3{id:3}))
WHERE
ANY (rel IN relationships(path) WHERE ANY(r IN rel.rights WHERE r IN usersRights)) AND
ANY (node IN nodes(path) WHERE ANY(r IN node.rights WHERE r IN usersRights))
RETURN path;
Upvotes: 0