у neo4j есть оператор минус - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь сравнить два графика, используя шифр.

Я довольно новичок в Cypher, поэтому не уверен, правильный ли это подход или нет, но если бы я делал это с помощью SQL, я бы использовал запрос NOT IN или MINUS. Я также пытался прочитать плагин алгоритмов графа для neo4j - я подозреваю, что один или несколько из них могут быть полезны, но я действительно не знаю, с чего начать.

Хочу заметить, что у cypher есть операторы UNION и UNION ALL, но нет оператора MINUS, так как мне сделать это в cypher? Опять же, если бы я использовал SQL, я мог бы легко достичь желаемого результата с помощью MINUS.

Во-первых, вот диаграмма моего графика:

Diagram of my sample data

В основном это Люди и Части. Люди делают часть. Например, «Боб» делает «роль Боба».

Существует зависимость между частями. Например, «Конечный продукт» состоит из «Партия Боба», «Партия Чарльза» и «Партия Артура».

Наконец, существует зависимость между людьми. В частности, поскольку Питер, который делает конечный продукт, нуждается в деталях от Боба, Артура и Чарльза, у Питера должны быть зависимости от Боба, Артура и Чарльза.

Однако связь между Чарльзом и Питером (показана красным) отсутствует в данных выборки. Это отношения, которые я пытаюсь определить.

Алгоритм, который я использую:

  1. Запрос 1: использование отношения "MADE_FROM", чтобы определить, какие части раньше делал другую часть. Это график с зелеными вершинами генерируется из зеленых отношений.

  2. Запрос 2: определите, какие детали используются для изготовления другой детали, следуя отношения людей и кто что делает. Это (или должно быть) граф, состоящий из зеленых вершин, но генерируется следуя отношениям MAKES и DEPENDS_ON.

К сожалению, из-за путаницы отсутствует красное отношение DEPENDS_ON, поэтому результаты двух запросов выше не совпадают.

Ниже приводится пример примечания о данных, что запись Peter,Charles,depends отсутствует:

id1,id2,relationship
Bob,Bobs Part,makes
Arthur,Arthurs Part,makes
Charles,Charles Part,makes
Peter,Final Product,makes
Peter,Bob,depends
Peter,Arthur,depends
Final Product,Arthurs Part,consists
Final Product,Bobs Part,consists
Final Product,Charles Part,consists

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

match(p:Person) detach delete p;
match(p:Part) detach delete p;

// Load the parts, people and who makes what relationship (Black relationship).
load csv with headers from 'file:///gmc/relationships.csv' as rec
with rec
where rec.relationship = "makes"
  create (person:Person {name: rec.id1})
  create (part:Part {partName: rec.id2})
  create (person) - [:MAKES] -> (part)
;

// Load the part relationships (green relationships)
load csv with headers from 'file:///gmc/relationships.csv' as rec
with rec
where rec.relationship = "consists"
  match (part:Part {partName: rec.id1})
  match (madeFrom:Part {partName: rec.id2})
  create (part) - [:MADE_FROM] -> (madeFrom)
;

// Load the people dependencies (blue relationships).
load csv with headers from 'file:///gmc/relationships.csv' as rec
with rec
where rec.relationship = "depends"
  match (person:Person {name: rec.id1})
  match (dependsOn:Person {name: rec.id2})
  create (person) - [:DEPENDS_ON] -> (dependsOn)
;

И, наконец, запросы, с которыми я работаю, чтобы создать «Отчет», который мне нужен:

neo4j> // Query1: Produce a list of parts and the parts that they are made from.
neo4j> // i.e. Final Product is made from Arthur's, Bob's and Charles' parts.
neo4j> match(part:Part)-[:MADE_FROM] -> (madeFrom:Part)
       return part, madeFrom
       order by part.partName, madeFrom.partName;
+--------------------------------------------------------------------------+
| part                                | madeFrom                           |
+--------------------------------------------------------------------------+
| (:Part {partName: "Final Product"}) | (:Part {partName: "Arthurs Part"}) |
| (:Part {partName: "Final Product"}) | (:Part {partName: "Bobs Part"})    |
| (:Part {partName: "Final Product"}) | (:Part {partName: "Charles Part"}) |
+--------------------------------------------------------------------------+

3 rows available after 1 ms, consumed after another 0 ms
neo4j> // Query 2: Produce a list of parts and the parts that they are made from
neo4j> // using the Dependencies that the people have on one another.
neo4j> match (part:Part) <- [:MAKES] - (person:Person)-[:DEPENDS_ON] -> (dependsOn:Person)-[:MAKES] -> (madeFrom:Part)
       return part, madeFrom
       order by part.partName, madeFrom.partName;
+--------------------------------------------------------------------------+
| part                                | madeFrom                           |
+--------------------------------------------------------------------------+
| (:Part {partName: "Final Product"}) | (:Part {partName: "Arthurs Part"}) |
| (:Part {partName: "Final Product"}) | (:Part {partName: "Bobs Part"})    |
+--------------------------------------------------------------------------+

2 rows available after 1 ms, consumed after another 0 ms
neo4j> // I need:  Query1 MINUS Query2   - which should produce
+--------------------------------------------------------------------------+
| part                                | madeFrom                           |
+--------------------------------------------------------------------------+
| (:Part {partName: "Final Product"}) | (:Part {partName: "Charles Part"}) |
+--------------------------------------------------------------------------+
neo4j> 

Окончательный набор ответов - это то, что я ищу. Это показывает мне, что «красные отношения» между Питером и Чарльзом отсутствуют, потому что:

  • часть, которую делает Питер (Конечный продукт), зависит от части, которую делает Чарльз (Часть Чарльза) Тем не менее,
  • они не зависят от Питера до Чарльза по пути "DEPENDS_ON".

Так как я могу сделать это с помощью шифра? Или я полностью лаю не то дерево с таким подходом ????

1 Ответ

2 голосов
/ 13 мая 2019

Есть небольшой шаг в переходе с SQL на Cypher. Старайтесь меньше думать о «таблицах» и больше об «отношениях». Требуется немного времени, но когда он щелкает, все становится немного более очевидным.

Этот запрос даст вам то, что вы хотите знать:

match (m:Person)-[:MAKES]->(x:Part)-[:MADE_FROM]->(y:Part)<-[:MAKES]-(n:Person)
where not (m)-[:DEPENDS_ON]-(n)  
return m,x,y,n

В основном, это ищет человека m, который делает деталь x, которая сделана из детали y, которая, в свою очередь, сделана человеком n, где m не связан с n. Способ написания запроса гарантирует, что m и n - это разные люди, а x и y - это разные части.

Эти типы рефлексивного «соединения» являются кошмаром в SQL, но относительно легки в Cypher.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...