沿遍历 Gremlin Cosmos DB 的价值聚合

Value Aggregation along Traversal Gremlin Cosmos DB

我需要执行以下形式的查询:我有一个树结构,在叶节点上有成本。我需要一个查询来为我提供根节点下的所有聚合成本。

例如在上图中,我希望查询的输出类似于

{ 1: 6, 2: 4, 3: 2, 4: 1, 5: 1, 6: 2, 7: 1, 8: 1}

我正在考虑为此使用 Gremlin API 中的 'sack' 步骤,但 cosmosDB 目前似乎不支持 sacks。我还尝试存储 "aggregated-cost" 的伪 属性 并从叶节点向上处理,但我无法弄清楚如何将每个节点的动态值存储为 属性 仅对那个节点是本地的。 考虑到这些限制,这种查询是否可行?

在询问有关 Gremlin 的问题时,最好包含一个简短的示例数据 Gremlin 脚本:

g.addV().property('id',1).as('1').
  addV().property('id',2).as('2').
  addV().property('id',3).as('3').
  addV().property('id',4).property('cost',1).as('4').
  addV().property('id',5).property('cost',1).as('5').
  addV().property('id',6).property('cost',2).as('6').
  addV().property('id',7).property('cost',1).as('7').
  addV().property('id',8).property('cost',1).as('8').
  addE('link').from('1').to('2').
  addE('link').from('1').to('3').
  addE('link').from('2').to('4').
  addE('link').from('2').to('5').
  addE('link').from('2').to('6').
  addE('link').from('3').to('7').
  addE('link').from('3').to('8').iterate()

根据 CosmosDB 中可用的步骤,我认为您可能最接近的是:

gremlin> g.V().
......1>   group().
......2>     by('id').
......3>     by(emit(has('cost')).
......4>        repeat(out()).
......5>        values('cost').
......6>        fold())
==>[1:[1,1,2,1,1],2:[1,1,2],3:[1,1],4:[1],5:[1],6:[2],7:[1],8:[1]]

group() 有助于生成您想要的 Map 结构。然后对于你分组的每个顶点,你使用 repeat() 遍历直到你到达叶顶点。请注意,emit() 确保仅返回那些带有 "cost" 属性 的顶点以用于结果目的。

我之所以说这与您使用 CosmosDB 所能达到的最接近,是因为我没有看到 CosmosDB 支持 sum() 步骤 here。如果是的话:

gremlin> g.V().
......1>   group().
......2>     by('id').
......3>     by(emit(has('cost')).
......4>        repeat(out()).
......5>        values('cost').
......6>        sum())
==>[1:6,2:4,3:2,4:1,5:1,6:2,7:1,8:1]

我猜你必须自己对返回的结果进行最后的计算。

对于其他人(或者当 CosmosDB 将来支持 sack() 时)你可以这样做:

gremlin> g.V().has('cost').
......1>   sack(assign).
......2>     by('cost').
......3>   emit().
......4>     repeat(__.in('link')).
......5>   group().
......6>     by('id').
......7>     by(sack().sum())
==>[1:6,2:4,3:2,4:1,5:1,6:2,7:1,8:1]

Gremlin Guru 提供。