Gremlin 查询以从 Cosmos 图中获取受影响的节点

Gremlin query to get affected nodes from the Cosmos graph

我们有一个如下所示的 Cosmos 图数据库。 IE。 A,B,C,... 是 nodes/vertices 并且边缘如箭头所示。

每个 node/vertex 代表 SQL table 中的一个值。流程及要求如下

  1. 用户修改SQL中的节点A值table
  2. Gremlin 查询将 A 传递到图形中
  3. 按下面列出的顺序绘制 returns 以下顶点
  4. C#app按顺序计算D,K,M,P节点的值并更新SQLtable

我尝试了以下查询,它有超过 3000 个 RU,这是非常昂贵的。

g.V("A").emit().repeat(__.in('depends')).until(__.inE().count().is(0))

我们需要一些帮助来优化查询。谢谢

更新===========

好的,我们可以在单个分区中重建图形以减少 RU,但我们有多个节点受到影响的场景,在下图中以红色突出显示,从 A 开始向上。

请问有人可以帮忙查询一下A、D、K、O、M、P顺序的结果吗?查询的逻辑是所有子节点都应该在它们的父节点之前列出

g.addV('ddn').property('pk', 'pk').property(id, 'A').property('formula', 'A').
addV('ddn').property('pk', 'pk').property(id, 'B').property('formula', 'B').
addV('ddn').property('pk', 'pk').property(id, 'C').property('formula', 'C').
addV('ddn').property('pk', 'pk').property(id, 'D').property('formula', 'A+B+C').property('requires', "'A','B','C'").
addV('ddn').property('pk', 'pk').property(id, 'E').property('formula', 'E').
addV('ddn').property('pk', 'pk').property(id, 'F').property('formula', 'E').
addV('ddn').property('pk', 'pk').property(id, 'G').property('formula', 'H+I').property('requires', "'H','I'").
addV('ddn').property('pk', 'pk').property(id, 'H').property('formula', 'H').
addV('ddn').property('pk', 'pk').property(id, 'I').property('formula', 'I').
addV('ddn').property('pk', 'pk').property(id, 'J').property('formula', 'F+G').property('requires', "'F','G'").
addV('ddn').property('pk', 'pk').property(id, 'K').property('formula', 'D+E+F').property('requires', "'D','E','F'").
addV('ddn').property('pk', 'pk').property(id, 'L').property('formula', 'L').
addV('ddn').property('pk', 'pk').property(id, 'M').property('formula', 'J+K').
addV('ddn').property('pk', 'pk').property(id, 'N').property('formula', 'N').
addV('ddn').property('pk', 'pk').property(id, 'O').property('formula', 'A+K').property('requires', "'A','K'").
addV('ddn').property('pk', 'pk').property(id, 'P').property('formula', 'L+M+N+O').property('requires', "'L','M','N','O'").
V('D').addE('needs').to(V('A')).
V('D').addE('needs').to(V('B')).
V('D').addE('needs').to(V('C')).
V('G').addE('needs').to(V('H')).
V('G').addE('needs').to(V('I')).
V('K').addE('needs').to(V('D')).
V('K').addE('needs').to(V('E')).
V('K').addE('needs').to(V('F')).
V('J').addE('needs').to(V('F')).
V('J').addE('needs').to(V('G')).
V('O').addE('needs').to(V('A')).
V('O').addE('needs').to(V('K')).
V('M').addE('needs').to(V('J')).
V('M').addE('needs').to(V('K')).
V('P').addE('needs').to(V('L')).
V('P').addE('needs').to(V('M')).
V('P').addE('needs').to(V('N')).
V('P').addE('needs').to(V('O'))

我认为答案归结为能够根据路径长度对遍历的顶点进行排序。

gremlin> g.V("A").
......1>   emit().repeat(__.in('needs')).path().
......2>   group().
......3>     by(tail(local)).
......4>     by(count(local).fold()).
......5>   order(local).
......6>     by(select(values).tail(local)).
......7>   select(keys)
==>[v[A],v[D],v[K],v[M],v[O],v[P]]

I group() 通过 path() 中的最后一个元素并将组中的每个路径转换为其长度 count(local)。这允许我 order() 每个顶点的最长路径的结果。

请注意,我认为您不需要 until(__.inE().count().is(0)),因为在任何一种情况下您都只是遍历到路径耗尽。另外,请注意 __.inE().count().is(0) ,因为您最终计算所有边缘只是为了检测计数为零。大多数图表应该将其优化为 until(inE()),但在我看来最好是明确的。也就是说,您在使用 repeat() 时需要确定您的数据结构 - 只需要一个错误数据的边缘就可以将您的遍历发送到无穷大的遍历中。考虑某种对您的数据有意义的 repeat() 上限,以便循环将在某个点终止。

这是一个实际上可能更好的替代方案,因为它不需要在 group() 之后保存 Map 中的所有计数:

gremlin> g.V("A").
......1>   emit().repeat(__.in('needs')).path().
......2>   group().
......3>     by(tail(local)).
......4>     by(count(local).order(local).tail(local)).
......5>   order(local).
......6>     by(values).
......7>   select(keys)
==>[v[A],v[D],v[K],v[M],v[O],v[P]]