Neo4j:跳过甚至只有一个匹配查询的关系的节点

时间:2017-12-01 20:26:45

标签: neo4j cypher

方案如下:

  • 我有一组x类型的节点,这些节点链接到y类型的节点。
  • 我希望匹配除x节点之外的所有y个节点,这些节点的属性等于特定值。

示例输入:

CREATE (a:x {name: 'a'}), (b:x {name: 'b'}), (c:x {name: 'c'});

CREATE (d:y {name: 'd', attrib: 1}), (e:y {name: 'e', attrib: 2}),
       (f:y {name: 'f', attrib: 3}), (g:y {name: 'g', attrib: 4}),
       (h:y {name: 'h', attrib: 5}), (i:y {name: 'i', attrib: 6});

MATCH (a), (d), (e) WHERE a.name = 'a' AND d.name = 'd' AND e.name = 'e'
CREATE (a)-[r:z]->(d), (a)-[s:z]->(e) RETURN *;

MATCH (b), (f), (g) WHERE b.name = 'b' AND f.name = 'f' AND g.name = 'g'
CREATE (b)-[r:z]->(f), (b)-[s:z]->(g) RETURN *;

MATCH (c), (h), (i) WHERE c.name = 'c' AND h.name = 'h' AND i.name = 'i'
CREATE (c)-[r:z]->(h), (c)-[s:z]->(i) RETURN *;

在这里,我想返回所有x个节点,但链接到y节点attrib = 5的节点除外。

这是我试过的:

MATCH (n:x)-[]-(m:y) WHERE NOT m.attrib = 5 RETURN n

通过此查询,我获得了所有x个节点,即:abc。我想排除c,因为它与h相关联,后者有h.attrib = 5

修改

我找到了一个完成这项工作的查询:

MATCH (n:x), (m:x)-[]-(o:y)
WHERE o.attrib = 5
WITH collect(n) as all_x_nodes, collect(m) as bad_x_nodes
RETURN [n IN all_x_nodes WHERE NOT n IN bad_x_nodes]

问题在于效率不高。还有更好的选择吗?

2 个答案:

答案 0 :(得分:0)

更好的方法是查找要排除的所有:x个节点(连接到具有特定属性的:y节点),收集这些x节点,然后匹配所有:x节点,这些节点不是在集合中:

MATCH (exclude:x)--(:y{attrib:5})
WITH collect(distinct exclude) as excluded
MATCH (n:x)
WHERE NOT n in excluded
RETURN collect(n) as result

使用APOC Procedures的另一种方法是获取两个集合,并从另一个集合中减去排除的集合:

MATCH (exclude:x)--(:y{attrib:5})
WITH collect(distinct exclude) as excluded
MATCH (n:x)
WITH excluded, collect(n) as nodes
RETURN apoc.coll.subtract(nodes, excluded) as result

在任何一种情况下,都有一个索引:y(attrib)。在这个数据集中,它并不重要。它将在更大的集合上。

答案 1 :(得分:0)

这个简单的查询应该完全符合您的要求:“返回除x节点之外的所有y节点,而attrib = 5节点具有MATCH (n:x) WHERE NOT (n)--(:y {attrib: 5}) RETURN n; 。”

>>> ft = 1 ^ a ^ 0 ^ b
>>> list(ft.satisfy_all())
[{a: 0, b: 0}, {a: 1, b: 1}]
相关问题