2015-06-29 3 views
1

У меня есть ориентированный график Neo4j, содержащий 2 типа узлов: узлы с метками в наборе 1 и узлы с метками в наборе 2. Я хотел бы создать новые ребра (нового типа) между узлами в Set 1, всякий раз, когда есть направленный путь от узла Set 1 к другому узлу Set 1, который проходит только через узлы Set 2 (возможно, 0 таких узлов Set 2).Создать граф из подмножества существующих узлов

Вот набор примеров данных:

CREATE (a:A {id:"a"})-[:CONN]->(t1:T {id:"t1"}), 
    (t1)-[:CONN]->(b1:B {id:"b1"}), 
    (b1)-[:CONN]->(t2:U {id:"t1"}), 
    (t2)-[:CONN]->(c1:C {id:"c1"}), 
    (c1)-[:CONN]->(t3:T {id:"t3"}), 
    (t3)-[:CONN]->(d1:D {id:"d1"}), 
    (t3)-[:CONN]->(d2:D {id:"d2"}), 
    (d1)-[:CONN]->(t4:T {id:"t4"}), 
    (d2)-[:CONN]->(t4), 
    (t4)-[:CONN]->(e1:E {id:"e1"}), 
    (t4)-[:CONN]->(e2:E {id:"e2"}) 

В этом примере A, B, C, D, & E в наборе 1, и T & U находятся в наборе 2, так что я хочу сделать новые :AGG края, как так:

MATCH (a:A {id:"a"}), (b1:B {id:"b1"}), (c1:C {id:"c1"}), (d1:D {id:"d1"}), 
     (d2:D {id:"d2"}), (e1:E {id:"e1"}), (e2:E {id:"e2"}) 
CREATE (a)-[:AGG]->(b1), 
    (b1)-[:AGG]->(c1), 
    (c1)-[:AGG]->(d1), 
    (c1)-[:AGG]->(d2), 
    (d1)-[:AGG]->(e1), 
    (d1)-[:AGG]->(e2), 
    (d2)-[:AGG]->(e1), 
    (d2)-[:AGG]->(e2) 

по отношению к CONN ребра, я знаю, что график - это DAG, поэтому мне не нужно беспокоиться о циклах.

Можно ли это сделать в Cypher? Или кто-то может предложить эффективный путь через интерфейсы Java (например, стратегию обхода)? Благодарю.

ответ

3

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

MATCH p=(node1)-[*]-(node2) 
WHERE ('A' in labels(node1) OR 
     'B' in labels(node1) OR 
     'C' in labels(node1) OR 
     'D' in labels(node1) OR 
     'E' in labels(node1)) 
     AND 
     ('A' in labels(node2) OR 
     'B' in labels(node2) OR 
     'C' in labels(node2) OR 
     'D' in labels(node2) OR 
     'E' in labels(node2)) 
     AND 
     (length(p) = 1 OR 
     all(intermedNode in 
      filter(n IN tail(nodes(p)) WHERE n <> last(nodes(p))) 
      WHERE 
      ('T' in labels(intermedNode) OR 
      'U' in labels(intermedNode)))) 
WITH node1, node2 
CREATE node1-[:MyNewNiftyEdge]->node2; 

Объяснение:

  1. Мы ищем пути; первые два больших блока WHERE просто доказывают, что источник и цель пути должны быть в «Set1».
  2. Последняя часть блока WHERE делает все, что угодно. Пути длины 1 в порядке (нулевые промежуточные узлы «Set2»). Но если есть промежуточные узлы, то мы делаем проверку, чтобы увидеть, все ли «внутренние» узлы «Set2». Бит filter с выражением tail просто отрубает первый и последний узлы с пути (мы уже знаем, что это node1 и node2). Затем выражение all настаивает на том, что если в середине есть что-то среднее, оно должно быть узлом Set2 (обозначается как «T» или «U»).
  3. Наконец, с этими двумя совпадающими узлами мы создаем отличные новые отношения, связывающие их напрямую.
+0

Awesome, спасибо. Я также начал кодировать решение с помощью интерфейса Java, если это сработает, я мог бы также опубликовать его здесь. –

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