2015-08-02 2 views
2

Я полностью newb для Neo4j, и я хочу создать общее количество для согласованного набора узлов. Вот что у меня естьNeo4j Running Total

MATCH n RETURN REDUCE(shares = 1000, p IN COLLECT(n) | shares - p.shares) 

Это просто decreaments от акций и отображает один результат, однако я что-то вроде ожидающим:

shares total 
100  100 
100  200 
100  300 

ответ

3

Да, вы можете сделать это, но вам нужно itemID или аналогичный по ваши узлы, чтобы обеспечить их заказ, иначе вы не сможете выполнить общую сумму. Вот как это может работать:

MATCH (f:F) 
WITH f 
OPTIONAL MATCH (g:F) 
WHERE g.itemID<f.itemID 
RETURN f.itemID, f.shares, sum(g.shares) + f.shares 
ORDER BY f.itemID ASC; 

Здесь я предполагаю, что у вас есть itemID на каждом узле. Это необходимо, потому что, если вы не знаете, какие узлы пришли раньше или меньше других, вы не можете вычислить текущую сумму. Но если у вас есть поле типа itemID, то вы делаете дополнительное необязательное соответствие для всех тех элементов, где itemID меньше, чем тот, на который вы смотрите, а затем вы суммируете эти доли. Это обеспечивает точный общий итог.

Это не очень эффективный запрос, поскольку вы суммируете и продолжаете повторное суммирование. Скажем, у вас 4 узла; первый ничего не суммирует. Вторая сумма одна. Третьи суммы 2 (один во второй раз). Четвертая сумма три (одна в третий раз, вторая во второй раз). Так что это много дополнительной работы.

Что мы здесь делаем, это взломать, чтобы не иметь изменяемой переменной. Если мне нужно было выполнить этот запрос, я обычно делал бы это из java/javascript/python/whatever. Я бы просто получил значение shares и вычислил текущую сумму за пределами cypher.

+0

Спасибо, что сработали. Реальная проблема заключается в том, что я пытаюсь выполнить алгоритм упаковки bin в neo4j. если я положу текущую логику в моем прикладном уровне, мне нужно сохранить транзакцию открытой по сети, которую я надеялся не делать. – Ryan

+0

Я тестировал 100 000 узлов, и да, производительность ужасна, мне пришлось ее остановить :( – Ryan

0

Попробуйте это:

MATCH (n:Item) 
RETURN sum(n.shares) as sum, collect(n.shares) as shares 
0

Этот вопрос был here по Mark Needham с другим методом:

WITH [100, 100, 100, 200, 300, 500] AS allShares 
UNWIND RANGE(0, LENGTH(allShares)-1) AS idx 
RETURN allShares[idx], 
REDUCE(acc = 0, 
     value in (allShares[idx] + allShares[..idx]) | 
     acc + value) AS cumulative 

- ==> +-----------------------------+ 
- ==> | allShares[idx] | cumulative | 
- ==> +-----------------------------+ 
- ==> | 100 | 100 | 
- ==> | 100 | 200 | 
- ==> | 100 | 300 | 
- ==> | 200 | 500 | 
- ==> | 300 | 800 | 
- ==> | 500 | 1300 | 
- ==> +-----------------------------+ 
- ==> 6 rows 

Я не проверял его производительность на больших наборов данных, но на первый взгляд это выглядит как это было бы значительно быстрее, чем принятый ответ.