Статьи

Neo4j 2.1: передача идентификаторов узлов против UNWIND

Когда выйдет Neo4j 2.1, у нас будет предложение UNWIND , которое облегчит работу с коллекциями.

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

Без предложения UNWIND мы бы сделали это:

01
02
03
04
05
06
07
08
09
10
11
12
13
MATCH (g:Group)
WITH g
ORDER BY g.name
LIMIT 5
  
WITH COLLECT(id(g)) AS groups
  
MATCH (g1) WHERE id(g1) IN groups
MATCH (g2) WHERE id(g2) IN groups
  
OPTIONAL MATCH path = (g1)<-[:MEMBER_OF]-()-[:MEMBER_OF]->(g2)
  
RETURN g1.name, g2.name, CASE WHEN path is null THEN 0 ELSE COUNT(path) END AS overlap

Здесь мы получаем первые 5 групп, помещаем их идентификаторы в коллекцию и затем создаем декартово произведение групп, выполняя спички MATCH с поиском идентификатора узла.

Если бы вместо передачи идентификаторов узлов в «группах» мы пропускали узлы, а затем использовали их в шаге MATCH, мы бы в итоге сделали полное сканирование узлов, которое становится очень медленным по мере роста хранилища.

например, эта версия будет очень медленной:

01
02
03
04
05
06
07
08
09
10
11
12
13
MATCH (g:Group)
WITH g
ORDER BY g.name
LIMIT 5
  
WITH COLLECT(g) AS groups
  
MATCH (g1) WHERE g1 IN groups
MATCH (g2) WHERE g2 IN groups
  
OPTIONAL MATCH path = (g1)<-[:MEMBER_OF]-()-[:MEMBER_OF]->(g2)
  
RETURN g1.name, g2.name, CASE WHEN path is null THEN 0 ELSE COUNT(path) END AS overlap

Это результат исходного запроса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
+-------------------------------------------------------------------------------------------------------------+
| g1.name                                         | g2.name                                         | overlap |
+-------------------------------------------------------------------------------------------------------------+
| "Big Data Developers in London"                 | "Big Data / Data Science / Data Analytics Jobs" | 17      |
| "Big Data Jobs in London"                       | "Big Data London"                               | 190     |
| "Big Data London"                               | "Big Data Developers in London"                 | 244     |
| "Cassandra London"                              | "Big Data / Data Science / Data Analytics Jobs" | 16      |
| "Big Data Jobs in London"                       | "Big Data Developers in London"                 | 52      |
| "Cassandra London"                              | "Cassandra London"                              | 0       |
| "Big Data London"                               | "Big Data / Data Science / Data Analytics Jobs" | 36      |
| "Big Data London"                               | "Cassandra London"                              | 422     |
| "Big Data Jobs in London"                       | "Big Data Jobs in London"                       | 0       |
| "Big Data / Data Science / Data Analytics Jobs" | "Big Data / Data Science / Data Analytics Jobs" | 0       |
| "Big Data Jobs in London"                       | "Cassandra London"                              | 74      |
| "Big Data Developers in London"                 | "Big Data London"                               | 244     |
| "Cassandra London"                              | "Big Data Jobs in London"                       | 74      |
| "Cassandra London"                              | "Big Data London"                               | 422     |
| "Big Data / Data Science / Data Analytics Jobs" | "Big Data London"                               | 36      |
| "Big Data Jobs in London"                       | "Big Data / Data Science / Data Analytics Jobs" | 20      |
| "Big Data Developers in London"                 | "Big Data Jobs in London"                       | 52      |
| "Cassandra London"                              | "Big Data Developers in London"                 | 69      |
| "Big Data / Data Science / Data Analytics Jobs" | "Big Data Jobs in London"                       | 20      |
| "Big Data Developers in London"                 | "Big Data Developers in London"                 | 0       |
| "Big Data Developers in London"                 | "Cassandra London"                              | 69      |
| "Big Data / Data Science / Data Analytics Jobs" | "Big Data Developers in London"                 | 17      |
| "Big Data London"                               | "Big Data Jobs in London"                       | 190     |
| "Big Data / Data Science / Data Analytics Jobs" | "Cassandra London"                              | 16      |
| "Big Data London"                               | "Big Data London"                               | 0       |
+-------------------------------------------------------------------------------------------------------------+
25 rows

Если мы используем UNWIND, нам больше не нужно передавать идентификаторы узлов, вместо этого мы можем собрать узлы в коллекцию и затем разложить их в декартово произведение:

01
02
03
04
05
06
07
08
09
10
11
12
13
MATCH (g:Group)
WITH g
ORDER BY g.name
LIMIT 5
  
WITH COLLECT(g) AS groups
  
UNWIND groups AS g1
UNWIND groups AS g2
  
OPTIONAL MATCH path = (g1)<-[:MEMBER_OF]-()-[:MEMBER_OF]->(g2)
  
RETURN g1.name, g2.name, CASE WHEN path is null THEN 0 ELSE COUNT(path) END AS overlap

Там не намного меньше кода, но я думаю, что цель запроса немного яснее, если использовать UNWIND.

Я с нетерпением жду возможности увидеть инновационные способы использования UNWIND, когда 2.1 — это GA.