Reputation: 24941
I have follwing simple graph:
CREATE (:leaf)<-[:rel]-(:nonleaf)<-[:rel]-(:nonleaf)<-[:rel]-(:nonleaf)<-[:rel]-(r1:nonleaf{root:true})<-[:rel]-(r2:nonleaf{root:true})
I want to get the first ancestor starting from (:leaf)
with root:true
set on it. That is I want to get r1
. For this I wrote following cypher:
MATCH (:leaf)<-[*]-(m)<-[*]-(r:nonleaf{root:true}) WHERE m.root<>true OR NOT exists(m.root)
RETURN r
But it returned both (r1)
and (r2)
. Same happened for following cypher:
MATCH shortestPath((l:leaf)<-[*]-(r:nonleaf{root:true}))
RETURN r
Whats going on here?
Update
Ok after thinking more, it clicked to my mind that (r2)
is also returned because on path from (:leaf)
to (r2)
, there are nodes with no root
property set on them (this should have clicked to me earlier, pretty much obvious, subtle interpretation mistake). In other words, it returns (:nonleaf{root:true})
if "for at least one m
" following condition is true: m.root<>true OR NOT exists(m.root)
. The requirement here is that the condition should be valid for "all m
s" on the path, "not at least one m
". Now it remains to figure out how to put this in cypher and my grip on cypher isnt that tight...
Upvotes: 2
Views: 363
Reputation: 11216
You just need to adjust your where condition a little so that it says "and the :nonleaf
node before the root :nonleaf
node matched is not itself marked as a root node". I think this will satisfy your needs.
MATCH (l:leaf)<-[*]-(r:nonleaf {root: true})
WHERE NOT (:nonleaf {root: true})<--(r)
RETURN r
UPDATED
Reading the updated example in the comments, I thought of another way to solve your problem using the APOC procedure apoc.path.expandConfig
.
It does require a slight change to your data. Each root: true
node should have a :root
label set on it. Here is an update statement...
MATCH (n:nonleaf {root:true})
SET n:root
RETURN n
And here is the updated query
MATCH (leaf:leaf {name: 'leaf'})
WITH leaf
CALL apoc.path.expandConfig(leaf, {relationshipFilter:'<rel',labelFilter:'/root'} ) yield path
RETURN last(nodes(path))
Upvotes: 1