我有简单的图表:
CREATE (:leaf)<-[:rel]-(:nonleaf)<-[:rel]-(:nonleaf)<-[:rel]-(:nonleaf)<-[:rel]-(r1:nonleaf{root:true})<-[:rel]-(r2:nonleaf{root:true})
我希望第一个祖先从(:leaf)
开始设置root:true
。那是我想获得r1
。为此我写了下面的密码:
MATCH (:leaf)<-[*]-(m)<-[*]-(r:nonleaf{root:true}) WHERE m.root<>true OR NOT exists(m.root)
RETURN r
但它返回了(r1)
和(r2)
。跟随密码发生了同样的事情:
MATCH shortestPath((l:leaf)<-[*]-(r:nonleaf{root:true}))
RETURN r
这是怎么回事?
更新
好好思考后,我点击了我的想法,(r2)
也会被返回,因为在从(:leaf)
到(r2)
的路径上,有些节点没有设置root
属性(这应该早点点击我,非常明显,微妙的解释错误)。换句话说,如果&#34;至少有一个(:nonleaf{root:true})
&#34; 以下条件为真,则返回m
:m.root<>true OR NOT exists(m.root)
。这里的要求是条件应该对路径上的&#34;所有m
s&#34; 有效,&#34;不是至少一个{{1 }}&#34; 即可。现在仍然需要弄清楚如何把它放在密码中,而我对cypher的控制并不紧张......
答案 0 :(得分:1)
您可以借助single()
谓词函数强制匹配路径上有一个根节点:
MATCH p=(:leaf)<-[*]-(r:nonleaf{root:true})
WHERE SINGLE(m IN nodes(p) WHERE exists(m.root) AND m.root=true )
RETURN r
答案 1 :(得分:1)
你只需稍微调整你的where条件就可以说&#34;并且匹配的根:nonleaf
节点之前的:nonleaf
节点本身不被标记为根节点&#34; 。我认为这将满足您的需求。
MATCH (l:leaf)<-[*]-(r:nonleaf {root: true})
WHERE NOT (:nonleaf {root: true})<--(r)
RETURN r
<强>已更新强>
阅读评论中的更新示例,我想到了另一种使用APOC程序解决问题的方法apoc.path.expandConfig
。
确实需要对您的数据进行细微更改。每个root: true
节点都应在其上设置:root
标签。这是更新声明......
MATCH (n:nonleaf {root:true})
SET n:root
RETURN n
这是更新的查询
MATCH (leaf:leaf {name: 'leaf'})
WITH leaf
CALL apoc.path.expandConfig(leaf, {relationshipFilter:'<rel',labelFilter:'/root'} ) yield path
RETURN last(nodes(path))