找到孤立的关系密码

时间:2013-12-02 19:57:52

标签: neo4j cypher

我想在图表中找到孤立的关系。例如,假设我有7个节点。 (n1到n7)。 n1只知道n2,而n2只知道n1 和n3-n6互相认识。 并且n7知道n6并且n6知道n7。

我想只返回n1和n2。 (因为它们只相互连接一次并且没有其他连接。(不同于n7和n6除了n7之外n6有连接)我搜索堆栈溢出并找到这个Neo4j - Cypher return 1 to 1 relationships。但是解决方案由于两个节点之间的双向关系,似乎在我的情况下不起作用。

使用遍历api可以很容易地实现这一点,但我想知道它是否可以在cypher中完成

这是neo4j控制台。我使用此查询返回节点只有1个连接http://console.neo4j.org/r/hvq7wr

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

考虑标准的另一种方式是你想要的模式是a)一个或两个深层关系,b)不是更长模式的一部分,c)只包含两个不同的节点,所以这就是我试图描述的在我上面的替代版本中。前两个标准很容易说明,但第三个标准并不像我想象的那么明显。我觉得可能有一种更简单的方法,如果你看到它就做编辑或评论。 (我首先尝试使用distinct而不是filter(),但我必须感到困惑,因为我无法让它工作。)