首页 文章

Cypher查询以查找最短的部分路径并聚合结果

提问于
浏览
0

我试图找到每个人的节点之间遍历的最小检查点 . 每个人都可以遍历多条路径 .

例:

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 .

我不需要包括那些已经被排除在外的人,因为他们没有在另一次遍历中进入上一个检查站 .

例:

  • person1应该只显示他们没有进入chkpt1 .

  • person2应该只显示他们没有进入chkpt3 .

  • person3显示在chkpt3中,因为它们完成了到最终chkpt3的所有路径 .

我想总结那些进入某个检查站的人的数量 . 因为可能有多个人进入最短的检查站 .

我还尝试将所有查询与多个 OPTIONAL MATCH 子句组合在一起,但是当节点数量增加时,这会慢下来 .

总节点将达到100,000到100万 . 实际遍历将仅涉及1000个节点,因为将根据某些值过滤人员 .

1 回答

  • 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.)如果可能,您可以考虑检查数据模型并将人员和检查点存储为单个节点,并在它们之间添加路径 . 这是一个更像图形的表示,应该有助于制定有效的查询 .

相关问题