Gremlin实现决策图路径分值累加的相关技术问题咨询
解决方案
你遇到的是Gremlin语法的固有特性限制:lt/gt/inside等P谓词仅支持传入静态字面量,无法直接接收遍历上下文的动态值作为比较参数,该问题无需大幅调整现有建模,仅修改遍历写法即可解决,优化方法如下:
核心优化点
1. JSON参数传入
Gremlin原生支持Map类型参数传递,你原有inject()的写法完全可用,也可以替换为withSideEffect()全局存储输入参数,写法更简洁:
g.withSideEffect('data', ["age":45, "income_source":"job"])
2. 动态比较的替代写法
放弃is(P)的谓词写法,改用where('别名', 谓词('别名'))的双别名比较语法,即可实现动态值的对比:
// 错误写法:lt()内传入动态遍历结果 where(select('data').select('val1').is(lt(select('data').values('val2')))) // 正确写法:先将两个比较值存为别名再对比 where(select('data').select('val1').as('v1').select('data').select('val2').as('v2').where('v1', lt('v2')))
注意:你当前构建图的代码中,边的min、max属性存储为字符串类型,比较前必须转换为数值,否则会出现类型不匹配错误
可直接运行的业务查询
修改后的查询可以直接输出你期望的47分值结果:
g.withSack(0). // 传入输入参数 withSideEffect('data', ['age':45, 'income_source':'job']). V().hasLabel('begin'). repeat( outE('relation').as('e'). // 提取边的规则参数与对应输入值 project('var', 'val', 'min', 'max', 'input_val'). by('var'). by('val'). by(values('min').map {it.get().toInteger()}). by(values('max').map {it.get().toInteger()}). by(select('data').select(select('var')).fold()). // 过滤符合规则的边 filter( choose(select('val').is(neq('')), // 等值规则校验 select('input_val').unfold().as('iv').select('val').as('ev').where('iv', eq('ev')), // 区间规则校验,跳过min=-1、max=-1的无规则边 choose(select('min').is(eq(-1)).and(select('max').is(eq(-1))), constant(true), select('input_val').unfold().as('iv').where('iv', gte(select('min'))).where('iv', lte(select('max'))) ) ) ). // 进入目标顶点累加分值 select('e').inV().sack(sum).by('score') ). until(hasLabel('decision')). project('final_score', 'path'). by(sack()). by(path().by(elementMap()))
可选建模优化(非必需)
如果要进一步提升查询性能,可以做小的建模调整:
- 提前将边的
min、max属性存储为整数类型,省略遍历过程中的类型转换步骤 - 给边增加
rule_type属性,标记是等值规则、区间规则还是无规则,减少遍历中的choose判断次数
内容的提问来源于stack exchange,提问作者gremlin
相关产品推荐
相关产品推荐

