如何在Gremlin查询中使用多个union步骤完成对应Cypher语句转换
Cypher转Gremlin完整实现
你提供的Cypher逻辑本质是返回所有以id=123的Group为端点/中间节点的无过期(边无Ceased On属性)的Member_Of可变长度路径,四个Union分支分别覆盖四类路径场景,对应的Gremlin实现如下:
g.V().hasLabel('Group').has('id', 123).as('root') .union( // 对应第一个Cypher分支:root <-[Member_Of*]- Person __.repeat( inE('Member_Of').hasNot('Ceased On').outV() ).emit().until(hasLabel('Person')).path(), // 对应第二个Cypher分支:root <-[Member_Of*]- Group ->[Member_Of*]- Group __.repeat( inE('Member_Of').hasNot('Ceased On').outV() ).emit().until(hasLabel('Group')) .repeat( outE('Member_Of').hasNot('Ceased On').inV() ).emit().until(hasLabel('Group')).path(), // 对应第三个Cypher分支:root ->[Member_Of*]- Group __.repeat( outE('Member_Of').hasNot('Ceased On').inV() ).emit().until(hasLabel('Group')).path(), // 对应第四个Cypher分支:root <-[Member_Of*]- Group <-[Member_Of*]- Person __.repeat( inE('Member_Of').hasNot('Ceased On').outV() ).emit().until(hasLabel('Group')) .repeat( inE('Member_Of').hasNot('Ceased On').outV() ).emit().until(hasLabel('Person')).path() )
语法说明(解决union使用困惑)
union()里的每个子遍历都从当前激活的节点(也就是id=123的Group节点)独立执行,多个子遍历的结果会合并去重返回,和Cypher的UNION语义完全对应。- 对源顶点入边关联的顶点做后续遍历,直接在对应子遍历的
repeat步骤里嵌套后续的边遍历逻辑即可,不需要调整union的整体结构,每个子遍历内部的逻辑互相独立不干扰。 - 所有边都加了
hasNot('Ceased On')过滤,和原Cypher的NONE(rel in rels WHERE EXISTS(rel.``Ceased On``))语义完全一致,遍历的每一步都会过滤不符合条件的边,自动截断无效路径。 repeat()后加的emit()参数用于返回所有长度匹配的路径(和Cypher可变长度匹配所有符合条件路径的逻辑一致),如果只需要返回终止节点匹配的最长路径,删除emit()即可。
如果你需要提取路径中所有边的Name属性,可以在上述查询后追加属性提取逻辑:
// 提取路径全属性+所有边的Name列表 g.V().hasLabel('Group').has('id', 123) .union(/* 上面的四个子遍历内容不变,此处省略 */) .project('fullPath','edgeNames') .by(valueMap(true)) .by(unfold().hasLabel('Member_Of').values('Name').fold())
内容的提问来源于stack exchange,提问作者Ranjit Soni
相关产品推荐
相关产品推荐

