2016-03-15 3 views
2

Использование Neo4J 2.1.5.Очень медленный этот запрос cypher, есть ли какая-нибудь оптимизация?

данных:

2000 человек
Цель: Для каждого человека, рассчитать общее количество друзей, друзей, друзей друзей друзей друзей.
Результат выглядит следующим образом:
Person FullName | Всего друзей | Друзья-2 всего | Друзья-3 всего | глобально всего

MATCH (person:Person) 
WITH person 
OPTIONAL MATCH person-[:KNOWS]-(p2:Person) 
WITH person, count(p2) as f1 
OPTIONAL MATCH path = shortestPath(person-[:KNOWS*..2]-(f2:Person)) 
WHERE length(path) = 2 
WITH count(nodes(path)[-1]) AS f2, person, f1 
OPTIONAL MATCH path = shortestPath(person-[:KNOWS*..3]-(f3:Person)) 
WHERE length(path) = 3 
WITH count(nodes(path)[-1]) AS f3, person, f2, f1 
RETURN person._firstName + " " + person._lastName, f1, f2, f3, f1+f2+f3 AS total 

Трюки во избежание неправильных расчетов с использованием циклического графика; поэтому я использую shortestPath.

Однако этот запрос длится долго: 60 секунд! Любая оптимизация возможна?

ответ

1

[EDITED]

Это работает для вас?

MATCH (person:Person) 
OPTIONAL MATCH (person)-[:KNOWS]-(p1:Person) 
WITH person, COALESCE(COLLECT(p1),[]) AS p1s 
WITH person, CASE p1s WHEN [] THEN [NULL] ELSE p1s END AS p1s 
UNWIND p1s AS p1 
OPTIONAL MATCH (p1)-[:KNOWS]-(p2:Person) 
WHERE NOT ((p2 = person) OR (p2 IN p1s)) 
WITH person, p1s, COALESCE(COLLECT(DISTINCT p2),[]) AS p2s 
WITH person, p1s, CASE p2s WHEN [] THEN [NULL] ELSE p2s END AS p2s UNWIND p2s AS p2 
OPTIONAL MATCH (p2)-[:KNOWS]-(p3:Person) 
WHERE NOT ((p3 = person) OR (p3 IN p1s) OR (p3 IN p2s)) 
WITH person, 
    CASE p1s WHEN [NULL] THEN 0 ELSE SIZE(p1s) END AS f1, 
    CASE p2s WHEN [NULL] THEN 0 ELSE SIZE(p2s) END AS f2, 
    COUNT(DISTINCT p3) AS f3 
RETURN person.firstName + " " + person.lastName, f1, f2, f3, f1+f2+f3 AS total; 

Каждый друг считается только один раз.

Вот объяснение некоторых более неясных тактик. Запрос должен заменить пустые p1s и p2s коллекциями с [NULL] так, чтобы UNWIND не прервал оставшуюся часть запроса. Затем, подсчитывая размер коллекций, нам нужно дать [NULL] коллекции 0.

+0

f1 является правильным, но он не возвращает хороших результатов для f2 и f3. Я ожидаю 51 для f2, но он возвращает 73. – Mik378

+0

Я не понимаю, что может быть неправильным в вашем запросе ... – Mik378

+0

Добавление 'distinct':' COLLECT (distinct p2) 'помогает, но все равно 53 вместо 51. – Mik378

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