2013-09-18 5 views
6

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

root 
| 
\-- A 
    | 
    \-- 1 
    | 
    \-- 2 
  • А ссылки на корень
  • 1 и 2 Ссылка на
  • корень родитель
  • 1 и 2 являются дети A

Поскольку я использую nodejs (с node-neo4j), чтение базы данных ограничивается использованием Cypher. Для чтения узлов я использую следующий запрос:

START n=node(1) 
    -- this is the root node 

MATCH (n)<-[linkedby:links*]-x, x-[linksto?:links*1]->() 
    -- get all nodes that link to the root node and all nodes linking to those nodes, etc, etc and retrieve all nodes those found nodes link to 

RETURN n, x, linkedby, LAST(linkedby) AS parent, COLLECT(DISTINCT linksto) AS links  
    -- the last in the path of linkedby is the direct parent 

ORDER BY length(linkedby), parent.rank? 
    -- ordering so that parents are fetched before their children from the result set 

Моя проблема: этот запрос становится очень медленным (> 1 с), поскольку число узлов и отношений расти.

Есть ли лучший способ моделирования узлов и отношений? Мне нужны разные отношения между родительскими узлами и дочерними узлами? Или мне нужно каким-либо образом изменить запрос?

Спасибо за любые указатели!


1) Реальный мир проблема: Своеобразного бизнес-процесс инструмента, где услуги связаны с процессами, организациями, группой и т.д., чтобы предоставить информацию, которые требуются услуги, когда и кто, а также предоставление информации кто будет предоставлять эту услугу или несет ответственность.

Так, например:

служба S используется в способе P1 и P2:

P1 P2 
| | 
\---+-- S 

Сервис S управляется командой T:

T 
| 
\-- S 

Команда Т является частью организации O:

O 
| 
\-- T 

Дерево:

root 
| 
| 
+-- Processes 
| | 
| +-- P1 
| | | 
| | \-- S 
| | 
| \-- P2 
| | | 
| | \-- S 
| 
+-- Organisations 
| | 
| +-- O 
|  | 
|  \-- T 
|   | 
|   \-- S 

2) Мои данные в console.neo4j.org:

CREATE 
    (r {name:'root'}), 
    (ps {name: 'Processes'})-[:links]->r, 
    (p1 {name: 'P1'})-[:links]->ps, 
    (p2 {name: 'P2'})-[:links]->ps, 
     (s {name: 'Service'})-[:links]->p1, 
     s-[:links]->p2, 
    (org {name: 'Organisations' })-[:links]->r, 
    (t {name: 'Team'})-[:links]->org, 
     s-[:links]->t 
+0

1. Можете ли вы представить реальную проблему мира, что вы пытаетесь решить. 2. Настройте свои данные в console.neo4j.org и share (кнопка сверху). –

+0

интересный вопрос, жалость нет ответов или подсказки на некоторые примеры кода онлайн –

+0

yep люди больше не отвечают на реальные вопросы: D просто тривиальные для репутации фермы. Я могу ответить на это немного. –

ответ

1

Итак, у меня был разговор с Michael Hunger другой день, и он признал, что Cypher не хорошо (пока) при обработке рекурсивной запросы. Это должно измениться в 2.1, но до этого он предложил написать unmanaged extension, который я мог бы затем вызвать из nodejs.

Это полностью решило мою проблему: извлечение дерева с использованием простой Java примерно в 10 раз быстрее, чем использование Cypher.

упрощенный код:

public class EntitiesStream { 
    public Entity load(long nodeId) { 
     Node n = database.getNodeById(nodeId); 
     Entity entity = Entity.from(n); 
     loadChildren(n, entity); 
     return entity; 
    } 

    private void loadChildren(Node n, Entity e) { 
     for (Relationship linksFrom: n.getRelationships(Direction.INCOMING, Relationships.links)) { 
      Node startNode = linksFrom.getStartNode(); 
      Entity childEntity = Entity.from(startNode); 
      e.addChild(((Number) linksFrom.getProperty("rank")).longValue, childEntity); 
      this.loadChildren(startNode, childEntity); 
     } 
    } 
} 

public class Entity { 
    private final TreeMap<Long, Entity> sortedChildren; 

    Entity(long dbId) { 
     this.sortedChildren = new TreeMap<>(); 
     // ... 
    } 

    public static Entity from(Node node) { 
     Entity e = new Entity(node.getId()); 
     // ... 

     return e; 
    } 

    public void addChild(Long rank, Entity childEntity) { 
     sortedChildren.put(rank, childEntity); 
    } 
} 
+0

Изменилось ли это в 2.1? – Tvaroh

+0

Любопытно, что я тестировал свое приложение с Neo4j 2.3.1, а запрос Cypher примерно на 20% быстрее по сравнению с 2.0.3. Тем не менее, нет, где рядом с выполнением расширения. – Sonata

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