2016-12-01 7 views
2

Рассмотрим простой пример с двумя типами узлов: компанией и работником. Для любых компаний c1 и c2 (которые уважают некоторые условия, которые я проигнорирую здесь), мне нужно знать: 1. Сколько у них рабочих, сколько у работников c1, и сколько у работников c2.Neo4j Путь Cypher, использующий несколько раз тот же край

Моя первая догадка:

MATCH (w_c1:Worker)--(c1:Company)--(w_common)--(c2:Company)--(w_c2:Worker) 
WHERE <something> 
RETURN c1, c2, COUNT(DISTINCT w_common), COUNT(DISTINCT w_c1), COUNT(DISTINCT w_c1) 

Проблема с этой просьбой в том, что, если у меня есть только одна связь между любой парой связанных узлов, COUNT (DISTINCT w_c1) (идентификатор w_c2) не только подсчитывать работник c1, который не является общим с c2. Но если у меня есть несколько отношений между некоторыми узлами, результаты иногда «правильные». Похоже, что путь в матче не «возвращается»: (w_common) - (c2: Company) - (w_c2: Рабочий) не будет соответствовать («worker1») - («company2») - («worker1») (что может иметь смысл избегать бесконечных циклов).

Моя вторая догадка разделить запрос на две части: Моя первая догадка:

MATCH (c1:Company)--(w_common)--(c2:Company) 
MATCH (c1)--(w_c1:Worker), (c2)--(w_c2:Worker) 
WHERE <something> 
RETURN c1, c2, COUNT(DISTINCT w_common), COUNT(DISTINCT w_c1), COUNT(DISTINCT w_c1) 

Но тогда, результаты правильно, но у меня есть предупреждение о декартовых продуктах, и в самом деле, по большому dataset, мой запрос не завершается через часы. Я попытался с помощью «WITH c1, w_common, c2» между двумя совпадениями, но у меня все еще есть предупреждение

Как мне продолжить?

ответ

1

Одна вещь, которая поможет вам, - это функция SIZE(), которая может рассказать вам количество вхождений шаблона, например, число: Рабочие на: Компания.

Этот запрос может работать для вас, если предположить, что работник работает в компании только один отношение к этой компании:

MATCH (c1:Company)--(w_common:Worker)--(c2:Company) 
WHERE <your criteria for matching on a specific c1 and c2> 
RETURN COUNT(w_common) as inCommonCount, SIZE((c1)--(:Worker)) as c1Count, SIZE((c2)--(:Worker)) as c2Count 
+0

Спасибо, я действительно выполнял функцию SIZE, но у меня может быть несколько отношений между данной компанией и работником (например, для нескольких рабочих периодов). – Vandy

+1

У вас есть определенный тип, например ': HIRED', который может появляться только один раз для Работника? Тогда вы можете сделать что-то вроде 'size ((c1) - [: HIRED] ->())'. –

1

Вы можете использовать промежуточные суммы:

OPTIONAL MATCH (C1:Company {name: 'c1'}) 
OPTIONAL MATCH (C2:Company {name: 'c2'}) 
WITH C1, C2 
MATCH (C:Company)<-[:workto]-(W:Worker) WHERE C = C1 OR C = C2 
WITH C1, C2, W, 
    sum(CASE WHEN C = C1 THEN 1 ELSE 0 END) as tmp1, 
    sum(CASE WHEN C = C2 THEN 1 ELSE 0 END) as tmp2 
RETURN C1, C2, 
     sum(tmp1) as cc1, sum(tmp2) as cc2, 
     sum(tmp1 * tmp2) as common 
Смежные вопросы