如何在Python中使用Gremlin为顶点列表添加度数属性
我尝试为顶点列表中的每个顶点添加度数(即与该顶点相连的顶点数量)属性。
生成每个顶点度数的查询是可行的:
c.g.V(ids).as_('vertex'). \ both(). \ groupCount(). \ by(select('vertex')).toList()
为所有顶点设置固定度数的查询也可行:
c.g.V(ids).as_('vertex'). \ both().groupCount().by(select('vertex')).unfold(). \ sideEffect( __.select(Column.keys).property(Cardinality.single, "degree", 1) ).toList()
但尝试保存顶点自身度数时出现错误。查询会对顶点分组,得到顶点到度数的字典,在sideEffect中选择顶点后,尝试将对应值存入属性失败。我尝试过的查询语句如下:
c.g.V(ids).as_('vertex'). \ both().groupCount().by(select('vertex')).unfold(). \ sideEffect( __.store('x').select(Column.keys).property(Cardinality.single, "degree", cap('x')).select(Column.values)) ).toList()
c.g.V(ids).as_('vertex'). \ both().groupCount().by(select('vertex')).unfold(). \ sideEffect( __.store('x').select(Column.keys).property(Cardinality.single, "degree", __.select(Column.values)) ).toList()
我希望从分组结果中提取Column.values并插入到属性中,请问我的查询存在什么问题?
编辑:
当前采用的实现方案如下,但运行极慢(实际查询包含大量has和hasLabel语句,进一步降低速度)。我发现第一个查询速度快得多,因此尝试基于它进行优化:
c.g.V(ids).property(Cardinality.single, "degree", __.both() .count()).iterate()
你的查询问题所在
取值逻辑错误:
unfold()后流中的每个元素是Map.Entry(键为顶点,值为度数)。你在sideEffect里直接用__.select(Column.values)作为property的参数行不通——property的第三个参数需要具体值,而非遍历器步骤,且当前上下文没有正确关联到Entry的value。
第一个错误查询里的store('x')+cap('x')逻辑混乱,无法正确提取度数,还会破坏遍历上下文。遍历上下文丢失:
拆分分组结果后,你没有明确在sideEffect里绑定顶点和对应的度数,导致设置属性时无法正确获取到对应的值。
正确的高效查询
基于你那个高效的groupCount查询,正确写法是在unfold()后拆分顶点和度数,再批量设置属性:
from gremlin_python.process.traversal import Column c.g.V(ids).as_('vertex'). \ both().groupCount().by(select('vertex')).unfold(). \ sideEffect( __.project('target_v', 'degree_val') .by(Column.keys) .by(Column.values) .select('target_v') .property(Cardinality.single, 'degree', __.select('degree_val')) ).iterate()
或者用更简洁的Lambda写法(适合Gremlin Python):
from gremlin_python.process.traversal import Column c.g.V(ids).as_('vertex'). \ both().groupCount().by(select('vertex')).unfold(). \ sideEffect( lambda entry: entry[Column.keys].property(Cardinality.single, 'degree', entry[Column.values]) ).iterate()
为什么这个查询高效
这个查询和你最初的groupCount查询效率一致:它只遍历所有目标顶点的邻接点一次,完成分组计数后批量设置属性。而你之前的慢查询是每个顶点单独遍历邻接点计数,当顶点数量大时,这种N次遍历的开销会指数级上升,加上has/hasLabel过滤后,每个顶点的计数都要重复执行过滤逻辑,速度自然极差。
内容的提问来源于stack exchange,提问作者Guy

