2013-12-02 4 views
1

Я хочу найти изолированные отношения на графике. Например, допустим, у меня 7 узлов. (от n1 до n7). n1 знает только n2, а n2 знает только n1 и n3-n6 знает друг друга. И n7 знает n6 и n6 знает n7.найти изолированные отношения cypher

Я хочу вернуть только n1 и n2. (потому что они только соединяются друг с другом один раз и не имеют другого выходного соединения (отличное от n7 и n6, из которых n6 выходит из соединения, кроме n7). Я просматриваю переполнение стека и нахожу это Neo4j - Cypher return 1 to 1 relationships. Однако решение не похоже работать в моем случае из-за двунаправленной связи между двумя узлами.

Это может быть очень легко выполнить с помощью траверсы апи, но я хочу, чтобы посмотреть, можно ли это сделать в шифром или не

Здесь это консоль neo4j. Я использую этот запрос для возврата узлов, у которых есть только одно соединение http://console.neo4j.org/r/hvq7wr

ответ

0

Похоже, что этот запрос решает мою проблему, но открыт для других эр предложение также

match (a:Node)-[:KNOWS]-> (b:Node) 
with a, count(*) as count 
where count = 1 
match (a)-[r:KNOWS]->(c)-[r1:KNOWS]->(d:Node) 
where id(a)<id(c) 
with a,c, collect(r1) as rs 
where length(rs)=1 
return a,c 

я бы, вероятно, использовать count во второй части тоже:

MATCH (a:Node)-[:KNOWS]->(b:Node) 
WITH a, count(*) AS count 
WHERE count = 1 
MATCH (a)-[r:KNOWS]->(c)-[r1:KNOWS]->(d:Node) 
WHERE id(a)<id(c) 
WITH a,c, count(DISTINCT r1) AS rs 
WHERE rs=1 
RETURN a,c 
+0

Это отлично работает, если [: KNOWS] всегда симметричен. Если есть случаи, которые не являются симметричными, вы можете получить ложные срабатывания и негативы, см. Http://console.neo4j.org/r/mbm5gc – jjaderberg

+0

В моем случае KNOWS всегда симметричен. Но вы действительно нашли хороший момент в ситуации, когда они не симметричны. Было бы неплохо разместить решение для этого. – dbspace

0

Я думал, что я пытаюсь придумать альтернативу, которая работает также, если отношения не симметричны , или если вы хотите представить симметрию, оставив направление отношений в своих запросах, а не с двойными отношениями в базе данных (на карту поставлены тысячи байтов, как сказал бы Джек Бауэр). Моя первая мысль была бюстом, но я думаю, что это работает:

MATCH p=(a:Node)-[:KNOWS]-(b:Node)-[r:KNOWS*0..1]-(c:Node) 
WHERE NOT (a)-[:KNOWS*3]-() AND NOT (b)-[:KNOWS*3]-() 
WITH a, reduce(
    allNodes = [], path in collect(p) | allNodes + filter(
     n in nodes(path) WHERE NOT n IN allNodes 
    ) 
) as allNodes 
WHERE length(allNodes) = 2 
RETURN a 

Когда я запускаю этот запрос в Neo4j console я говорил, что я делаю что-то исключительное (спасибо!), Это говорит Error: org.neo4j.kernel.guard.GuardOperationsCountException: max ops (ops=10001). Может быть, это намек на улучшение запроса (?), Но он отлично работает, когда я запускаю его локально.

В принципе я понял, если не

(a)-[:KNOWS]->(b) => (b)-[:KNOWS]->(a) 

, то вы можете получить ложные срабатывания с вашим запросом, когда (b:Node) имеет ровно один исходящие отношения, но это не (a:Node) и ложноотрицательные при (b:Node) не имеют исходящих связей.

(a)-[:KNOWS]->(b)-[:KNOWS]->(c) AND a<>c // false positive 
(a)-[:KNOWS]->(b) AND NOT (b)-[:KNOWS]->() // false negative 

Другой способ думать критериев является то, что шаблон, который вы хотите это) один или два отношения глубоки, б) не является частью более длинной модели, с) содержит только два отдельных узлов, так это то, что Я попытался описать в моей альтернативной версии выше. Первые два критерия были легко сформулированы, но третий был менее очевидным, чем я думал. Я чувствую, что есть, вероятно, гораздо более простой способ, редактировать или комментировать, если вы это видите. (Я сначала попытался использовать distinct, а не filter(), но я должен быть смущен, потому что я не мог заставить это работать).

+0

Я понимаю, как избавиться от ложных положительных, но все же нужно получить ложный отрицательный.MATCH (a: Node) - [: KNOWS] -> (b: Node) С a, count (*) AS count WHERE count = 1 MATCH (a) - [r: KNOWS] -> (c) - [r1: KNOWS] -> (д: узел) WHERE ID (а) <идентификатор (с) с, с, длина (сбор (R1)), как RS где г = 1 с а, с MATCH (a) - [: KNOWS] -> (c) - [r2: KNOWS] -> (e: Node) WHERE id (a) = id (e) с a, c совпадение (f: узел) - [r: KNOWS] -> (a) где id (f) <> id (c) с длиной a, c (collect (r)) как rs2 где rs2 = 0 return a, c – dbspace

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