我有100个带有标签A的节点和2个带有标签B的节点.所有带有标签A的节点都与至少一个带有标签B的节点相关.如何获得标签A的所有节点都与标签B的两个节点相关?我尝试过以下方法:
MATCH p=(:A)-[:TYPE]->(b:B) where b.Name = 'XYZ' or b.Name = 'ABC'
RETURN p
Run Code Online (Sandbox Code Playgroud)
这只给了我与这两个节点中的任何一个节点相关的所有节点.
编辑:我已设法通过使用以下查询执行此操作:
MATCH (a:A)- [:TYPE] ->(t:Type) where t.Name = 'ABC'
MATCH (a:A)- [:TYPE] -> (u:Type) where u.Name = 'XYZ'
return a, t, u
Run Code Online (Sandbox Code Playgroud)
有没有办法优化这个?
有几种方法可以做到这一点.
如果:TYPE关系:A节点只连接到:B节点,并且每个节点之间只有一个:TYPE关系:A和:B节点,那么最快的方法是根据以下程度过滤:TYPE关系来自:一个节点:
MATCH (a:A)
WHERE SIZE((a)-[:TYPE]->()) = 2
RETURN a
Run Code Online (Sandbox Code Playgroud)
如果:TYPE关系不仅仅是:B节点,那么您可以稍微更改查询.它不会那么高效,但它会正常工作:
MATCH (a:A)
WHERE SIZE((a)-[:TYPE]->(:B)) = 2
RETURN a
Run Code Online (Sandbox Code Playgroud)
如果B节点的数量增加,并且您想要找到:连接到所有:B节点的节点,那么我们可以使用集合以及ALL()函数来获得正确的集合:A节点:
MATCH (b:B)
WITH COLLECT(b) as bnodes
MATCH (a:A)
WHERE ALL(b in bnodes WHERE (b)<-[:TYPE]-(a))
RETURN a
Run Code Online (Sandbox Code Playgroud)
如果您只需要B节点的子集,而不是全部,那么您可以根据ID的集合过滤初始匹配:
// assuming you supply a list parameter of ids called 'ids'
MATCH (b:B)
WHERE b.id in {ids}
WITH COLLECT(b) as bnodes
WITH HEAD(bnodes) as first, bnodes
MATCH (a)-[:TYPE]->(first)
WHERE ALL(b in TAIL(bnodes) WHERE (b)<-[:TYPE]-(a))
RETURN a
Run Code Online (Sandbox Code Playgroud)
那里有一些额外的逻辑只考虑:一个节点是你的bnodes中的一个元素的类型.这样我们就不会考虑:与您的任何bnode无关的节点,使我们无法进行不必要的比较.