如何为Gremlin的union步骤添加元数据识别元素来源遍历?
解决方案
要实现union后追踪元素来源,同时处理去重和多来源记录,推荐使用分组聚合的方式,既能正确去重,又能收集每个元素的所有来源标记。
实现代码
.union( // 给第一个子遍历的元素绑定标记t1,包装成[元素, 标记]的列表 select('parent').out('contains').map(union(identity(), constant('t1')).fold()), // 给第二个子遍历的元素绑定标记t2,包装成[元素, 标记]的列表 select('parent2').out('contains').map(union(identity(), constant('t2')).fold()) ) // 按元素本身分组,收集所有对应的来源标记 .group() .by(head()) // 取列表第一个元素(即原始顶点)作为分组键 .by(tail().fold()) // 取列表第二个元素(标记)并收集为列表 // 展开分组后的键值对,转换为目标结构 .unfold() .project('id', 'traversal') .by(keys().id()) // 提取元素ID .by(values()) // 提取来源标记列表
代码说明
- 绑定来源标记:每个子遍历用
map(union(identity(), constant('标记')).fold())将顶点和来源标记组合成列表,避免修改顶点原有属性。 - 分组去重:通过
group()按顶点本身分组,自动实现去重,同时将同一顶点的所有来源标记收集到一个列表中(如果顶点同时出现在两个子遍历,标记列表会是['t1','t2'])。 - 结构转换:用
unfold()展开分组结果,再通过project()输出id和traversal字段。
替代方案(临时属性法)
如果不介意临时修改顶点属性(遍历结束后临时属性会自动清除),可以用以下方式:
.union( select('parent').out('contains').property('__source__', 't1'), select('parent2').out('contains').property('__source__', 't2') ) .group() .by(identity()) .by(values('__source__').fold()) .project('id', 'traversal') .by(id()) .by(values())
注:使用带前缀的临时属性名(如__source__),避免与顶点原有属性冲突。
你之前方案的问题
你之前用map(group().by(identity()).by(constant('t1')))生成的是独立的Map对象,每个Map的引用不同,导致dedup()无法识别出相同的顶点,自然无法去重。而分组聚合的方式直接以顶点本身作为分组依据,从根源解决了去重和来源追踪的问题。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

