2017-02-15 18 views
1

У меня есть загрузка пользователей и фотографий с тремя возможными связями между ними (с потенциально более добавленными позже). Эти отношения: POSTED_BY, APPEARS_IN и MENTIONED_IN. Для конкретного пользователя я хочу получить запрос, который возвращает свою сеть до n. Например, это должно включать фотографии, которые они опубликовали, фотографии, которые они отображают или упоминаются в них, а также учетные записи, на которых были размещены эти фотографии.Ограничение по каждому узлу, а не целому запросу

Мой запрос на данный момент:

MATCH (root:account { username: {username} })-[r*1..4]-(u) 
RETURN * 
LIMIT 50 

Проблема с этим состоит в том, что предел делается на основе общих строк. Это приводит только к возврату одного узла уровня 1, когда у него много подносов. Вот более наглядное объяснение проблемы.

Это то, что она может выглядеть с обычным пользователем (упрощенный):

enter image description here

Если первый узел найден имеет много фотографий, это то, что получает возвращается:

enter image description here

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

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

+0

Это проблема рекурсии, которая в настоящее время отсутствует в cypher. И я думаю, что эта проблема не может быть решена с помощью одного cypher-запроса, если цель - эффективность (скорость и ресурсы). –

+0

Несомненно, должен быть способ ограничить количество узлов, возвращаемых в каждом «прыжке», а не на весь запрос? –

ответ

0

Вы можете сделать это с шифром, ограничивая длину пути:

MATCH path=(root:account { username: {username} })-[r*1..4]-(u) 
WITH COLLECT(path) as paths 
RETURN filter(x in paths WHERE length(x)<50) 

Вы можете сделать это, используя Neo4j Traversal API. В оценщике вы можете проверить длину пути и обрезать, если путь больше требуемой длины.

import org.neo4j.graphdb.Direction; 
import org.neo4j.graphdb.Path; 
import org.neo4j.graphdb.traversal.Evaluation; 
import org.neo4j.graphdb.traversal.Evaluator; 

public class MyEvaluator implements Evaluator{ 

    @Override 
    public Evaluation evaluate(Path path) { 
     if(path.length()>=50) 
     {   
      return Evaluation.INCLUDE_AND_PRUNE; 
     } 

     return Evaluation.INCLUDE_AND_CONTINUE; 
    } 
} 
+0

Это не решит проблему, которую я боюсь. Это просто фильтрует до путей, длина которых меньше 50, что не является моей проблемой. Мне нужно ограничить количество детей, которые могут иметь каждый узел. Ваш запрос требует сканирования всей базы данных, которая будет очень медленной. –

0

Я думаю, что нужно что-то вроде следующего:

MATCH (root:account { username: {username} })-[]-> (child1)-[r*1..4]-(u) 
RETURN child1, collect(u) 
LIMIT 50 

это будет возвращать до 50 строк каждая строка будет иметь две колонки. Первый столбец будет child1s и второй столбец будет иметь «нас» этого ребенка

0

Вы можете построить этот запрос вручную:

MATCH (root:account { username: {username} }) 
WITH {ids: [root], rels: []} as graph 

UNWIND graph.ids as N 
    MATCH (N)-[r]->(C) WHERE NOT C IN graph.ids 
    WITH graph, C, r LIMIT 50 
    WITH graph, collect(C) as ids, collect(r) as rels 
    WITH {ids: ids + graph.ids, rels: graph.rels + rels} as graph 

UNWIND graph.ids as N 
    MATCH (N)-[r]->(C) WHERE NOT C IN graph.ids 
    WITH graph, C, r LIMIT 50 
    WITH graph, collect(C) as ids, collect(r) as rels 
    WITH {ids: ids + graph.ids, rels: graph.rels + rels} as graph 

UNWIND graph.ids as N 
    MATCH (N)-[r]->(C) WHERE NOT C IN graph.ids 
    WITH graph, C, r LIMIT 50 
    WITH graph, collect(C) as ids, collect(r) as rels 
    WITH {ids: ids + graph.ids, rels: graph.rels + rels} as graph 

UNWIND graph.ids as N 
    MATCH (N)-[r]->(C) WHERE NOT C IN graph.ids 
    WITH graph, C, r LIMIT 50 
    WITH graph, collect(C) as ids, collect(r) as rels 
    WITH {ids: ids + graph.ids, rels: graph.rels + rels} as graph 

RETURN graph.rels 

Конечно, эта структура может быть получена с помощью простой конкатенации по javascript в случае больших переходов.