在Neo4j中,自动生成关系后来导致重复结果

时间:2016-03-02 16:35:53

标签: neo4j duplicates unique

在下面的代码中,我手动创建了3个节点,然后是它们之间的三个有向关系。当我查询所有可能的“定向”组合时,我得到了我所期望的:7种组合。这是你可以削减的代码。粘贴到Neo4j浏览器中......

CREATE (a:Component {name:'A'})
CREATE (b:Component {name:'B'})
CREATE (c:Component {name:'C'})

CREATE (a)-[:CanExistWith]->(b),  
       (a)-[:CanExistWith]->(c),  
       (b)-[:CanExistWith]->(c)

WITH a,b,c
MATCH p = (:Component)-[*0..]->(:Component)
RETURN EXTRACT(n IN nodes(p)| n.name) AS component_sets

..和7集的正确结果:

[A], [B], [C], [A,B], [A,C], [B,C], [A,B,C]

这样工作正常;只有3个组件(节点),它是可行的 Relationships individually specified by hand

但如果图表有20个组件,我将不得不手动创建超过一百万个组合关系。当然,REST客户端无论如何都无法处理 没关系,Neo4j可以自动化那部分。因此,让我们将节点数保持为3,并将手动创建关系的中间代码块更改为使用MATCH + CREATE UNIQUE子句自动生成它们。

CREATE (a:Component  {name:'A'})
CREATE (b:Component  {name:'B'})
CREATE (c:Component  {name:'C'})

WITH a,b,c    
MATCH (x:Component ), (y:Component )
WHERE id(x) < id(y)
CREATE UNIQUE (x)-[r:CanExistWith]->(y)

WITH x,y
MATCH p = (:Component )-[*0..]->(:Component )
RETURN EXTRACT(n IN nodes(p)| n.name) AS component_sets

如果你运行它并且你看看它在Neo4j浏览器中创建的视觉图形,它在视觉上与上面的相同。它们具有相同数量的节点和关系,箭头指向正确的方向 Relationships auto-generated via MATCH + CREATE UNIQUE

但是第二张图实际上表现不同。当我查询所有可能的独特定向组合时,我得到重复:

[A], [A], [A], [B], [B], [B], [C], [C], [C], 
[A, B], [A, B], [A, C], [A, C], [A, C], [B, C],
[A, B, C]

有16组而不是7组。我知道我可以使用DISTINCT进行清理,但我没有在第一个例子中,并且随着节点数量的增加,重复数量会爆炸。这里不需要DISTINCT,因为路径选择和任何修剪应该能够在MATCH时间发生。我希望没有重复生成将意味着更高效的CYPHER代码。

所以问题是:如何更改我的图形结构或自动关系构建查询以获得与第一个示例相同的结果?

(我使用的是Neo4j版本2.3.2)

1 个答案:

答案 0 :(得分:1)

问题出在&#39; WITH&#39;。 &#39; WITH&#39;关键字做2件事;它连接连续的查询,并将变量从一个查询转发到下一个查询。在这种情况下,没有必要继续推进的变量。而且似乎包含哪些变量并不重要:&#39; WITH x,y&#39;或者只是&#39; WITH x&#39;或者&#39;与x,r,y&#39;或只是与r&#39;。 所有这些都产生16行数据,大多数是重复的行。

在这种情况下的诀窍是省略&#39; WITH&#39;条款完全。该条款以某种方式导致重复。它不会作为一个脚本运行,但结果是完美的!所以这是两个脚本。代码中没有任何内容被更改,除了缺少的&#39; WITH x,y&#39;。

首先运行:

CREATE (a:Component  {name:'A'})
CREATE (b:Component  {name:'B'})
CREATE (c:Component  {name:'C'})

WITH a,b,c    
MATCH (x:Component ), (y:Component )
WHERE id(x) < id(y)
CREATE UNIQUE (x)-[r:CanExistWith]->(y)

......然后这个:

MATCH p = (:Component )-[*0..]->(:Component )
RETURN EXTRACT(n IN nodes(p)| n.name) AS component_sets

..它产生7组的正确结果:

[A], [B], [C], [A,B], [A,C], [B,C], [A,B,C]