2015-09-18 2 views
9

У меня есть дерево с множеством уровней, где листовые узлы могут иметь свойство «count». Я хочу рассчитать общий счетчик для каждого поддерева и кэшировать эти значения в корневом узле каждого поддерева. Возможно ли это в Гремлине?Как рассчитать агрегаты для поддеревьев в Гремлине?

+0

какой версии Gremlin 2.x или 3.x? –

+0

Gremlin 2.x предпочтительнее. – isobretatel

ответ

3

Вы можете сделать это с помощью 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() 

хранение сумму «подсчета» для каждого поддерева в переменной с именем c. Там есть немного отличной доброты с оператором elvis (?:), чтобы проверить вершины без свойства «count» и вернуть нуль в этих случаях. После обхода дерева, чтобы вычислить c вы можете просто хранить значение c в корневом узле поддерева через:

it.setProperty('total',c) 
+0

>> Вы можете просто сохранить значение c в корневом узле поддерева << Как? – isobretatel

+0

'v1.setProperty ('total', c)' - вам нужно что-то еще? –

+0

Да: вычислять и кэшировать эти значения для _each_ sub-tree, а не для всего дерева. – isobretatel

Смежные вопросы