【发布时间】:2017-10-05 01:33:31
【问题描述】:
我试图找到每个人在节点之间遍历的最小检查点。每个人可以穿越多条路径。
例子:
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 个节点,因为人员将根据某个值进行过滤。
【问题讨论】:
-
这些轨迹(路径)是否单独存储在图中?例如,您是否为 person1 创建了两个节点? (因为您的第一个查询返回 person1,我相信是这种情况。)
-
每个人都是一个有多个边的节点。
-
您是否有固定(少量)的检查点,或者这也会发生变化?
-
如果检查点很多,这很重要,最好使用通用标签(例如
:Checkpoint)和属性(例如step)。另外,我在您的示例中添加了一个数字并进行了一些更改——请仔细检查。 -
@JeffNewbie 在您提供的数据库中,每个人都有 1 个优势。 (而且我无法理解架构)如果您将架构更改为使用一组检查点(由一些
:Next关系连接)并且每个人都作为与他们所做的每个检查点的:Reached关系,您的查询可能只是MATCH (person:person) OPTIONAL MATCH (person)-[:REACHED]->(cp:chkpt) RETURN person, COUNT(cp) as checkpoints ORDER BY checkpoints(根据需要过滤。不太确定您真正想要的最终结果是什么)这是我的意思的example。