我正在尝试找到每个人在节点之间遍历的最小检查点。每个人都可以遍历多条路径。
示例:
CREATE
(:person {id: 0}),
(:person {id: 1})-[:rel1]->(:chkpt1 {id: '1'})-[:rel2]->(:chkpt2 {id: '2'}),
(:person {id: 2})-[:rel1]->(:chkpt1 {id: '1_1'}),
(:person {id: 2})-[:rel1]->(:chkpt1 {id: '1_2'})-[:rel2]->(:chkpt2 {id: '2_1'}),
(:person {id: 2})-[:rel1]->(:chkpt1 {id: '1_3'})-[:rel2]->(:chkpt2 {id: '2_2'})-[:rel3]->(:chkpt3 {id: '3_1'}),
(:person {id: 3})-[:rel1]->(:chkpt1 {id: '1_4'})-[:rel2]->(:chkpt2 {id: '2_3'})-[:rel3]->(:chkpt3 {id: '3_2'}),
(:person {id: 3})-[:rel1]->(:chkpt1 {id: '1_5'})-[:rel2]->(:chkpt2 {id: '2_4'})-[:rel3]->(:chkpt3 {id: '3_3'}),
(:person {id: 3})-[:rel1]->(:chkpt1 {id: '1_6'})-[:rel2]->(:chkpt2 {id: '2_5'})-[:rel3]->(:chkpt3 {id: '3_4'})
目前,我正在使用OPTIONAL MATCH
子句并运行多个查询,如下所示:
MATCH (p:person)
OPTIONAL MATCH (p)-[:rel1]-(cp1:chkpt1)
WITH p, cp1
WHERE cp1 IS NULL
RETURN p.id
返回:person0
然后我运行一个单独的查询来查找没有进入下一个检查点的所有人。
MATCH (p:person)-[:rel1]-(cp1:chkpt1)
OPTIONAL MATCH (cp1)-[:rel2]-(cp2:chkpt2)
WITH p, cp1, cp2
WHERE cp2 IS NULL
RETURN DISTINCT p.id, cp1.id
返回:person2
同样适用于下一个检查点。
MATCH (p:person)-[:rel1]-(cp1:chkpt1)-[:rel2]-(cp2:chkpt2)
OPTIONAL MATCH (cp2)-[:rel3]-(cp3:chkpt3)
WITH p, cp1, cp2, cp3
WHERE cp3 IS NULL
RETURN DISTINCT p.id, cp1.id, cp2.id
返回:person1和person2
我想只返回person1,因为person2错过了之前的遍历。
MATCH (p:person)-[:rel1]-(cp1:chkpt1)-[:rel2]-(cp2:chkpt2)-[:rel3]-(cp3:chkpt3)
RETURN DISTINCT p.id, cp1.id, cp2.id
返回:person2和person3
但是,我想只返回person3,因为person2没有进入chkpt3和chkpt2。
我不需要包括那些已经被排除在外的人,因为他们没有进入另一次遍历的前一个检查站。
示例:
我想总结那些进入某个检查站的人数。由于可能有多人进入最短的检查站。
我还尝试将所有查询与多个OPTIONAL MATCH
子句组合在一起,但当节点数量增加时,这种情况会慢下来。
总节点数将达到100,000到100万。实际遍历将只涉及1000个节点,因为将根据某些值过滤人员。
答案 0 :(得分:0)
但是,我想只返回person3,因为person2没有进入chkpt3和chkpt2。
这个查询怎么样?它计算一个人参与的遍历次数,并检查他们是否在所有遍历中都进入了检查点3。
MATCH (p:person)-[r]-()
WITH p, count(r) AS allTraversals
MATCH (p)-[:rel1]-(cp1:chkpt1)-[:rel2]-(cp2:chkpt2)-[:rel3]-(cp3:chkpt3)
WITH p, allTraversals, count(cp3) AS cp3s
WHERE allTraversals = cp3s
RETURN p
(注意:这不适用于person0
。)
另外,有几点意见:
(1。)您可以使用WHERE NOT <pattern>
结构以更简洁的方式制定负面条件。
MATCH (p:person)
WHERE NOT (p:person)-[:rel1]->(:chkpt1)
RETURN p
(2。)如果可能,您可以考虑检查数据模型并将人员和检查点存储为单个节点,并在它们之间添加路径。这是一个更像图形的表示,应该有助于制定有效的查询。