【问题标题】:Stop Cypher traversal when where condition on reduce() can no longer be satisfied当 reduce() 上的条件不再满足时停止 Cypher 遍历
【发布时间】:2026-02-21 22:35:01
【问题描述】:

假设我有一个具有单一节点类型和单一关系类型的 neo4j 数据库以保持简单。所有关系都有一个“成本”属性(如在经典图问题中),其值为非负数。

假设现在我想找到 ID A 的节点和 ID B 的节点之间的所有可能路径,路径长度的上限(例如 10)使得总路径成本低于或等于给定常数(例如 20)。

完成此操作的 Cypher 代码如下(并且有效):

START a = node(A), b = node(B)
MATCH (a) -[r*0..10]-> (b)
WITH extract(x in r | x.cost) as costs, reduce(acc = 0, x in r | acc + x.cost) as totalcost
WHERE totalcost < 20
RETURN costs, totalcost

这个查询的问题是它没有利用成本是非负的这一事实,因此可以修剪通过总成本限制的路径。相反,它列出了节点 A 和 B 之间长度为 0 到 10 的所有可能路径(这可能非常昂贵),计算总成本,然后过滤掉超出限制的路径。及时修剪路径将带来巨大的性能提升。

我知道通过使用 BranchStates 并在相关时防止扩展使用遍历框架是可行的,但我想找到一个 Cypher 解决方案(主要是由于暴露的原因 here)。

我目前使用的是 2.2.2 版,如果这很重要的话。

【问题讨论】:

    标签: neo4j cypher traversal pruning


    【解决方案1】:

    提取之前的关系成本总和是否足够?

    START a = node(A), b = node(B)
    MATCH (a)-[r*0..10]->(b)
    WHERE sum(r.cost) < 20
    WITH extract(x in r | x.cost) as costs, reduce(acc = 0, x in r | acc + x.cost) as totalcost
    RETURN costs, totalcost
    

    顺便说一句,想要修剪意味着你想要命令式的方式!

    另外,请帮助 Cypher,使用标签

    【讨论】:

    • 如果我这样做,我会收到“无效使用聚合函数 sum(...)”。我感觉聚合函数不能在 WHERE 子句中使用(有点类似于 SQL)。关于标签,这不是我的原始密码,只是一个例子(正如我在第一句话中提到的,我们应该假设只有一种类型的节点和一种类型的关系,所以标签在这里并不重要,是吗? )。
    • 哦,关于“想要修剪”的部分,我不“想要”修剪。修剪会以更有效的方式返回我的结果(声明方式)。此外,指定结果是否可以修剪(或者可能指定更广泛的概念,例如属性的非负性)也不是必须的。