【问题标题】:In Neo4j, auto-generating relationships caused duplicate results later在 Neo4j 中,自动生成的关系导致后来出现重复的结果
【发布时间】:2016-03-02 16:35:53
【问题描述】:

在下面的代码中,我手动创建了 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 个组件(节点),这是可行的。

但如果图表有 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 浏览器中创建的可视化图形,它在视觉上与上面的图形相同。它们具有相同数量的节点和关系,箭头指向正确的方向。

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

[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 版)

【问题讨论】:

    标签: neo4j duplicates unique


    【解决方案1】:

    问题在于“WITH”。 “WITH”关键字做了两件事;它连接连续的查询,并将变量从一个查询传递到下一个查询。在这种情况下,没有需要结转的变量。似乎它包含哪些变量并不重要:'WITH x,y',或者只是'WITH x'或'WITH x,r,y'或只是'WITH r'。 所有这些都会产生 16 行数据,其中大部分是重复的行。

    在这种情况下,诀窍是完全省略“WITH”子句。该条款以某种方式导致了重复。它不会作为一个脚本运行,但结果是完美的!所以这是两个脚本。除了缺少的 'WITH x,y' 之外,代码中没有任何变化。

    首先运行这个:

    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]
    

    【讨论】:

      猜你喜欢
      • 2015-08-12
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      • 2016-09-23
      • 1970-01-01
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      相关资源
      最近更新 更多