我可以使用
之类的东西进行密码查询MATCH (a:A)-[]->(b:B)-[]->(c:C)-[]-(d1:D),
(a)-[]->(b)-[]->(c)-[]-(d2:D),
(a)-[]->(b)-[]->(c)-[]-(d3:D),
(a)-[]->(b)-[]->(c)-[]-(d4:D),
WHERE d1.val = '1' AND d2.val = '2' AND d3.val ='3', d4.val = '4'
RETURN a, b, c, d1, d2, d3, d4
有没有办法简化这个查询,而不是一遍又一遍地显式重写关系,这是相同的。我试图找到具有我期望的所有D
值的每个关系,这是一个很大的列表,所以可能IN
子句是合适的。
编辑: 基于以下答案的示例数据
create (a1:A {name: 'A1'})
create (b1:B {name: 'B1'})
create (c1:C {name: 'C1'})
create (d1:D {name: 'D1', val: 1})
create (d2:D {name: 'D2', val: 2})
create (d3:D {name: 'D3', val: 3})
create (d4:D {name: 'D4', val: 4})
create (a1)-[:NEXT]->(b1)
create (b1)-[:NEXT]->(c1)
create (c1)-[:NEXT]->(d1)
create (c1)-[:NEXT]->(d2)
create (c1)-[:NEXT]->(d3)
create (c1)-[:NEXT]->(d4)
create (a2:A {name: 'A2'})
create (b2:B {name: 'B2'})
create (c2:C {name: 'C2'})
create (a2)-[:NEXT]->(b2)
create (b2)-[:NEXT]->(c2)
create (c2)-[:NEXT]->(d1)
create (c2)-[:NEXT]->(d2)
create (a3:A {name: 'A3'})
create (b3:B {name: 'B3'})
create (c3:C {name: 'C3'})
create (a3)-[:NEXT]->(b3)
create (b3)-[:NEXT]->(c3)
create (c3)-[:NEXT]->(d1)
create (c3)-[:NEXT]->(d2)
create (c3)-[:NEXT]->(d3)
create (c3)-[:NEXT]->(d4)
return *
因此,查询应该会生成A1-->B1-->C1-->D1,D2,D3,D4
和A3-->B3-->C3-->D1,D2,D3,D4
由于A2-->B2--C2
仅与D1,D2
而非D3,D4
相关联,因此不应在结果中。
答案 0 :(得分:2)
如果每个D
节点都有唯一的val
属性(如果有的话),那么这应该有效:
WITH [1,2,3,4] AS desired
MATCH (a:A)-->(b:B)-->(c:C)-->(d:D)
WHERE d.val IN desired
WITH a, b, c, COLLECT(DISTINCT d) AS ds
WHERE SIZE(ds) = SIZE(desired)
RETURN a, b, c, ds
每个匹配的A
,B
,C
组合的结果以及D
个节点的集合都会有一行。
答案 1 :(得分:2)
路径的开头始终相同,因此您不需要重复它。然后,根据值列表,您要检查是否可以为每个值找到D
:它可能是all
的作业。
混合所有这些,我们得到:
MATCH (a:A)-->(b:B)-->(c:C)-->(d:D)
WHERE d.val IN {values}
WITH a, b, c, collect(d) AS dList
WHERE all(value IN values WHERE any(d IN dList WHERE d.val = value))
RETURN a, d, c, dList
但是,如果 n 是值的数量,那么由于第二个WHERE
,这是一个O(n ^ 2)算法。
让我们在收集节点本身的同时收集节点的值,以避免双循环并将其转换为O(n)算法:
MATCH (a:A)-->(b:B)-->(c:C)-->(d:D)
WHERE d.val IN {values}
WITH a, b, c, collect(d) AS dList, collect(DISTINCT d.val) AS dValues
WHERE all(value IN values WHERE value in dValues)
RETURN a, d, c, dList
假设作为参数传递的值列表仅包含不同的值,我们甚至可以通过简单地比较输入列表的大小和找到的不同值来将其更改为O(1)算法:
MATCH (a:A)-->(b:B)-->(c:C)-->(d:D)
WHERE d.val IN {values}
WITH a, b, c, collect(d) AS dList, collect(DISTINCT d.val) AS dValues
WHERE size({values}) = size(dValues)
RETURN a, d, c, dList
由于dValues ⊂ values
,如果2套具有相同的尺寸,则它们相等。
如果D.val
全局唯一,或者对于连接到单个D
的所有C
节点至少是唯一的,则可以进一步简化:
MATCH (a:A)-->(b:B)-->(c:C)-->(d:D)
WHERE d.val IN {values}
WITH a, b, c, collect(d) AS dList
WHERE size({values}) = size(dList)
RETURN a, d, c, dList
如果值是全局唯一的,则使用unicity约束查询会更快,因为它还会索引值:
CREATE CONSTRAINT ON (d:D) ASSERT d.val IS UNIQUE
答案 2 :(得分:1)
假设以下数据集......
create (a:A {name: 'A'})
create (b:B {name: 'B'})
create (c:C {name: 'C'})
create (d1:D {name: 'D1', val: 1})
create (d2:D {name: 'D2', val: 2})
create (d3:D {name: 'D3', val: 3})
create (d4:D {name: 'D4', val: 4})
create (a)-[:NEXT]->(b)
create (b)-[:NEXT]->(c)
create (c)-[:NEXT]->(d1)
create (c)-[:NEXT]->(d2)
create (c)-[:NEXT]->(d3)
create (c)-[:NEXT]->(d4)
return *
您可以执行类似这样的查询,以匹配特定值范围内的所有特定D
节点。
match (a:A)-->(b:B)-->(c:C)-->(d:D)
where d.val in range(1,4)
return *
以下是基于您更新的问题的更新查询。我收集了每个D
节点链的A,B,C
值。
match (a:A)-->(b:B)-->(c:C)-->(d:D)
where d.val in range(1,4)
with a, b, c, d
order by a.name, b.name, c.name, d.name
return a, b, c, collect(d) as d
order by a.name, b.name, c.name