2015-10-02 3 views
3

Я пытаюсь выполнить следующую задачу в запросе cypher, но я не получаю правильных результатов. В других вопросах stackoverflow обсуждаются лимиты или собираются, но я не думаю, что этого достаточно для выполнения следующей задачи.return top n результатов для каждого запроса в Neo4j

Задача: У меня есть (p: Product) узлы и между двумя узлами продукта есть связь, называемая «BOUGHT_TOGETHER». То есть

(p:Product)-[b:BOUGHT_TOGETHER]-(q:Product) 

И отношение b имеет свойство «размер», которое содержит некоторое число. Я хочу вернуть первые 3 результата для каждого отношения продукта, которое упорядочивается по размеру. Например, результат запроса должен выглядеть следующим образом.

+------------------------+ 
| p.id | q.id | b.size  | 
+------------------------+ 
    1  2  10 
    1  3  8 
    1  5  7 
    2  21  34 
    2  17  20 
    2  35  15 
    3  5  49 
    3  333  30 
    3  65  5 
    .  .  . 
    .  .  . 
    .  .  . 

Может ли кто-нибудь показать мне, как написать запрос cypher, чтобы достичь желаемых результатов? Спасибо!

ответ

1

Вот один способ сделать это (кажется, там должен быть способ использовать LIMIT, но я не мог придумать один только сейчас).

я произвел примерный график с

FOREACH (a IN [[1,2,10],[1,3,8],[1,5,7],[2,21,34],[2,17,20],[2,35,15],[3,5,49],[3,333,30],[3,65,5],[1,4,1],[3,6,100]]| MERGE (p:Product { id:a[0]}) 
    MERGE (q:Product { id:a[1]}) 
    CREATE p-[b:BOUGHT_TOGETHER { size:a[2]}]->q 
) 

Это данные из таблицы желаемого выхода, плюс два дополнительных пункта: [1,4,1] и [3,5,100]. Наличие более трех отношений для некоторых узлов помогает нам проверить, что запрос получает правильные три - результаты для 1 не должны содержать [1,4,1], а результат для 3 должен теперь содержать [3,6,100] вместо [3,5,5].

Если это точный образец данных, то этот запрос должен делать то, что вы хотите:

MATCH (p:Product)-[b:BOUGHT_TOGETHER]-(q:Product) 
WITH p.id AS pid, q.id AS qid, b.size AS bsize 
ORDER BY bsize DESC 
WITH pid, collect([qid, bsize])[..3] AS qb 
UNWIND qb AS uqb 
RETURN pid, uqb[0] AS qid, uqb[1] AS bsize 
ORDER BY pid, bsize DESC 

Идея заключается в том, чтобы заказать все элементы результата по b.size, а затем собрать их в p и выбросить все, кроме первых трех элементов в каждой коллекции, затем расслабляйтесь и возвращайтесь. Результаты не будут выглядеть точно так же, как и ваша выходная таблица, потому что она также включает отношения в другом направлении ([5,1,7], а также [1,5,7]), но я думаю, что вы все равно захотите.

Если это работает, вы можете посмотреть, можете ли вы отложить чтение свойств до тех пор, пока вы не обрезаете коллекции, чтобы сохранить некоторые удары базы данных.

3

Другое решением является первым порядком отношений, трубочные их в коллекции и UNWIND только 3 первых результатов коллекции:

MATCH (p:Product)-[r:BOUGHT_TOGETHER]->(:Product) 
WITH p, r 
ORDER BY r.size DESC 
WITH p, collect(r) AS bts 
UNWIND bts[0..3] AS r 
RETURN p.uuid as pid, endNode(r).uuid as qid, r.size as size 

Тест консоль здесь: http://console.neo4j.org/r/r88ijn

NB: После повторного читая ответ jjaderberg, это немного похоже на то, что я считаю более читаемым. Почему я голосовал за его ответ.

+0

Спасибо! это сработало! – user4279562

+0

круто, пожалуйста, примите ответ ;-) –

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