【问题标题】:How to calculate aggregates for sub-trees in Gremlin?如何计算 Gremlin 中子树的聚合?
【发布时间】:2015-12-16 03:02:32
【问题描述】:

我有一棵有很多层的树,其中叶节点可能具有属性“计数”。 我想计算每个子树的总数,并将这些值缓存在每个子树的根节点中。 Gremlin 有可能吗?

【问题讨论】:

  • Gremlin 2.x 或 3.x 哪个版本?
  • Gremlin 2.x 会更好。

标签: tree aggregate gremlin


【解决方案1】:

您可以使用 sideEffect 来实现 - 这非常简单。我们设置了一个简单的树:

gremlin> g = new TinkerGraph()                                                                 
==>tinkergraph[vertices:0 edges:0]
gremlin> v1 = g.addVertex()                                                                    
==>v[0]
gremlin> v2 = g.addVertex()                                                                    
==>v[1]
gremlin> v3 = g.addVertex([count:2])                                                           
==>v[2]
gremlin> v4 = g.addVertex([count:3])                                                           
==>v[3]
gremlin> v1.addEdge('child',v2)                                                                
==>e[4][0-child->1]
gremlin> v1.addEdge('child',v3)                                                                
==>e[5][0-child->2]
gremli                                                                                         
gremlin> v2.addEdge('child',v4)
==>e[6][1-child->3]

然后是整个树中每个子树的计算:

gremlin> g.V().filter{it.outE().hasNext()}.sideEffect{                                           
gremlin>   c=0;                                                                                  
gremlin>   it.as('a').out().sideEffect{leaf -> c+=(leaf.getProperty('count')?:0)}.loop('a'){true}.iterate()
gremlin>   it.setProperty('total',c)                                                                       
gremlin> }                                                                                                 
==>v[0]
==>v[1]
gremlin> g.v(0).total
==>5
gremlin> g.v(1).total                                                                                      
==>3

该查询像这样分解。首先,这件作品:

g.V().filter{it.outE().hasNext()}

获取树的任何不是叶子节点的部分(即,应该至少有一个出边不是叶子)。其次,我们使用sideEffect处理子树的每个根:

it.as('a').out().sideEffect{leaf -> c+=(leaf.getProperty('count')?:0)}.loop('a'){true}.iterate()

将每个子树的“count”属性的总和存储在名为c 的变量中。使用 elvis 运算符 (?:) 可以检查没有“计数”属性的顶点并在这些情况下返回零,这有一点非常棒的优点。在遍历树计算 c 后,您可以通过以下方式将 c 的值存储在子树的根节点中:

it.setProperty('total',c) 

【讨论】:

  • >>你可以只将 c 的值存储在子树的根节点中
  • v1.setProperty('total',c) - 你还需要什么吗?
  • 是:为每个子树计算并缓存这些值,而不是为整个树。
  • 我需要修改查询:属性'count'属于叶子顶点'知道'的顶点:v1 = g.addVertex() v2 = g.addVertex() v3 = g.addVertex() v4 = g.addVertex() v5 = g.addVertex([count:3]) v6 = g.addVertex([count:2]) v1.addEdge('child',v2) v1.addEdge('child',v3 ) v2.addEdge('child',v4) v3.addEdge('knows',v5) v4.addEdge('knows',v6)
  • 添加边缘标签并不会真正改变我提供的查询的结果。它按原样独立于边缘标签工作,我认为没有理由将其限制在标签上。您是否认为添加边缘标签会导致某些内容不再有效?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
  • 2019-06-18
  • 1970-01-01
  • 2017-02-10
  • 1970-01-01
  • 2020-08-10
相关资源
最近更新 更多