Запрос Cypher для соответствия сильным двухсторонним отношениям и фильтрации по значениям свойств в Neo4j

Я хотел бы найти подграф в Neo4j DB с сильными двусторонними отношениями.

Скажем, что отношение LOVES и атрибут Kisses, тогда я бы хотел найти только подграф, где обе стороны поцеловали другого более чем в 2 раза.

START n=node(*)
MATCH n-[r1:LOVES]->friend<-[r2:LOVES]-n
WHERE r1.Kisses > 2 and r2.Kisses > 2
RETURN n, friend, r1, r2
LIMIT 20

проблема заключается в том, что запрос, кажется, запускается вечно на графике отношений 3M node 30M, на 32-гигабайтной ОЗУ, четырехъядерной системе с 16-кратной максимальной кучей для neo4j (калькулятор neo4j предложил 8 ГБ).

Я подозреваю, что где-то скрывается бесконечная петля.

ОС: Ubuntu 12.04.1 Сервер LTS

Soft: neo4j-community-1.8.1

java version "1.7.0_10" (neo4j start говорит использовать JDK6)

Java (TM) SE Runtime Environment (сборка 1.7.0_10-b18)

64-разрядная серверная виртуальная машина Java HotSpot TM (сборка 23.6-b04, смешанный режим)

ИЗМЕНИТЬ: совпадение неверно, оно должно быть

MATCH n-[r1:LOVES]->friend-[r2:LOVES]->n

UPDATE: После исправления семантики выше, я все еще не могу получить полный результат за 5 минут.

ЛЮБОВЬ - это единственный тип отношения и около 10-20%, или отношения имеют соответствующий, идущий другим путем.

Моя конечная цель - найти подходящие значения Kiss, чтобы я остался с < 100k узлами (и всеми соответствующими отношениями LOVES) и мог экспортировать этот подграф.

Здесь псевдокод для алгоритма для того, что я пытаюсь сделать:

let E be edge.list to be processed
let myedgelist be empty list
for e in E:
 if e.n1 > e.n2: # so we do not look twice
 continue
 if not exist(e[n2][n1]): # this is where lookup can be a problem O(1) for hash, O(logn) for sorted, O(n) for something random)
 continue
 if e.kisses > 2 and e[n2][n1].kisses > 2:
 add e to myedgelist
 add e[n2][n1] to myedgelist
return myedgelist

Этот алгоритм должен работать не более edgecount * log (edgecount), если нет эффективного способа поиска обратного отношения в neo4j, что казалось бы немыслимым.

2 ответа

Можете ли вы попытаться сделать friend цель node

START friend=node(*)
MATCH n-[r1:LOVES]->friend-[r2:LOVES]->n
WHERE r1.Kisses > 2 and r2.Kisses > 2
RETURN n, friend, r1, r2
LIMIT 20

вы можете попытаться разбить матч на две части

START n=node(*)
MATCH n-[r1:LOVES]->friend
WHERE r1.Kisses > 2
WITH n,r1,friend
MATCH n<-[r2:LOVES]-friend
WHERE r2.Kisses > 2
RETURN n, friend, r1, r2
LIMIT 20

или, альтернативно, только половина запроса с совпадением, а вторая половина с фильтром

START n=node(*) 
MATCH n-[r1:LOVES]->friend 
WHERE r1.Kisses > 2 
 AND ALL(r2 in extract(
 p in friend-[:LOVES]->n : head(rels(p))) 
 WHERE r2.Kisses > 2) 
RETURN n, friend, r1
LIMIT 20

здесь консоль, чтобы попробовать запросы: http://console.neo4j.org/r/tqvb1p

Но ведь вы обрабатываете узлы 3M с совпадением, которое потенциально взрывается до 3M ^ 2


Вы должны попробовать это в 1.9 - для этого типа запроса значительно оптимизирован сопоставитель cypher. Хотя было бы неплохо избежать node (*). Все ли ваши узлы? Если нет, вы можете захотеть сделать индексный запрос, чтобы получить только соответствующие узлы.

start n=node:people("name:*")...

licensed under cc by-sa 3.0 with attribution.