Gremlin coalesce步骤未按Tinkerpop文档预期执行问题
问题根因
你碰到的是Amazon Neptune 1.1.0.0版本中Gremlin coalesce步骤的已知执行bug,和TinkerPop标准行为不一致的复现路径如下:
- 传入3个属性过滤分支时,预期返回第一个分支匹配的green顶点,实际返回最后一个分支匹配的yellow顶点,代码如下:
g.V() .coalesce( __.has("color", "green"), __.has("color", "blue"), __.has("color", "yellow") )
- 移除yellow分支后,实际返回第二个分支匹配的blue顶点,仍然不命中第一个green分支:
g.V() .coalesce( __.has("color", "green"), __.has("color", "blue") )
- 仅保留单个green分支时,执行逻辑恢复正常,正确返回green顶点:
g.V() .coalesce( __.has("color", "green") )
该bug的触发原因是Neptune 1.1.0.0的查询优化器对coalesce内连续的has属性过滤分支做了错误的逻辑改写,没有遵循TinkerPop标准中「对每个输入遍历器按顺序评估内部遍历,返回第一个能产出结果的遍历结果」的执行规则,反而直接取最后一个内部遍历的过滤条件做全局匹配。你提到的Sagemaker/Jupyter环境可复现属于正常情况,问题根源在服务端引擎版本,和客户端环境无关。
解决方法
- 不升级版本的临时规避:不需要修改业务语义,只需要在每个内部
has遍历前加一个无副作用的identity()步骤,就能阻断优化器的错误改写,让coalesce回到标准执行逻辑,修改后代码如下:
g.V() .coalesce( __.identity().has("color", "green"), __.identity().has("color", "blue"), __.identity().has("color", "yellow") )
- 永久修复:直接将Neptune引擎升级到1.2.0.0及以上版本,该bug在后续引擎迭代中已经被官方修复。
注意:不要尝试用
order().by('color', ...)加分组取首的写法替换coalesce,二者语义有本质区别:coalesce的逻辑是只要存在任意高优先级匹配的顶点,就完全不返回低优先级顶点;而排序写法会按单个顶点维度排序,可能同时返回不同优先级的结果,不符合原始业务预期。
内容的提问来源于stack exchange,提问作者Fook
相关产品推荐
相关产品推荐

