如何在Gremlin路径遍历查询中检查sack值并在其为0时终止遍历?
解决方案:在Gremlin中通过sack值判断即时终止遍历
我完全理解你的痛点——当sack值变为0时,后续的遍历已经没有任何意义,只会浪费查询资源。我们可以通过在repeat的循环条件中添加对sack值的检查,来实现遍历的即时终止。
问题分析
你的原始查询只在遍历边的时候判断了availablePath>0,但没有在每次遍历完成后检查sack的当前值。这就导致即使sack已经变成0(比如走到节点3时),遍历仍然会继续尝试后续的边,完全是无效操作。
修改后的查询语句
我们只需要在repeat内部的遍历步骤最后,添加一个sack().is(gt(0))的判断,确保只有当sack值大于0时,才会进入下一轮循环:
g.withSack(7).V().has('id','1') .local( repeat( bothE().where(values('availablePath').is(gt(0))) .sack{f,l -> f & l}.by('availablePath') .otherV() .simplePath() .as('node') .where(sack().is(gt(0))) // 核心新增:检查sack值,大于0才继续遍历 ).emit() .sack().as('path') ) .select('node','path') .by() .by() .dedup()
关键修改说明
- 终止条件添加:
.where(sack().is(gt(0)))会在每次完成一个节点的遍历后,检查当前的sack值。如果sack等于0,循环会立即终止,不会继续尝试后续的边。 - 保留边的有效性判断:
bothE().where(values('availablePath').is(gt(0)))的判断仍然需要保留,因为首先要确保这条边本身有可用路径,才值得去遍历。
可选:包含sack为0的节点
如果你希望把sack变为0的节点(比如示例中的节点3)也包含在结果里,可以调整emit的条件,让它同时捕获sack大于0和等于0的节点:
g.withSack(7).V().has('id','1') .local( repeat( bothE().where(values('availablePath').is(gt(0))) .sack{f,l -> f & l}.by('availablePath') .otherV() .simplePath() .as('node') ).emit(or(where(sack().is(gt(0))), where(sack().is(eq(0))))) // 同时保留有效路径和终止节点 .sack().as('path') ) .select('node','path') .by() .by() .dedup()
示例验证
用你提供的示例图测试:
- 原始查询会遍历到节点4(sack=7&3&4&7=0),但这是无效的,因为走到节点3时sack已经是0了。
- 第一个修改后的查询会在节点3处终止,只返回节点2(sack=3),不会继续走到节点4。
- 第二个可选查询会返回节点2(sack=3)和节点3(sack=0),满足你想记录终止节点的需求。
内容的提问来源于stack exchange,提问作者ayc
相关产品推荐
相关产品推荐

