【问题标题】:Neo4j: Applying index and constraint changes query resultsNeo4j:应用索引和约束更改查询结果
【发布时间】:2021-06-09 22:06:29
【问题描述】:

我遇到了 Neo4j 的问题,在应用以下内容后,同一查询的结果会发生变化:

  • 具有给定标签的节点的属性索引
  • 一个约束,它断言与上面具有相同标签的节点存在相同的属性

环境

  • Neo4j 版本:4.2.1 Enterprise,默认运行时(插槽)
  • Neo4j 桌面 1.4.1
  • 操作系统:macOS Big Sur 11.4 版

重现步骤:

通过运行以下命令创建一组节点和关系:

CREATE (p1:Person { id: '100', name: 'Hampton Fancher' })<-[:WRITTEN_BY]-(m:Movie { id: '101', name: 'Blade Runner' })-[:BASED_ON]->(n:Novel { id: '102', name: 'Do Androids Dream of Electric Sheep?' })-[:WRITTEN_BY]->(p2:Person { id: '103', name: 'Philip K Dick' })

通过运行以下命令创建第二组节点和关系:

CREATE (p1:Person { id: '200', name: 'Phil Alden Robinson' })<-[:WRITTEN_BY]-(m:Movie { id: '201', name: 'Field of Dreams' })-[:BASED_ON]->(n:Novel { id: '202', name: 'Shoeless Joe' })-[:WRITTEN_BY]->(p2:Person { id: '203', name: 'W P Kinsella' })

运行此查询:

MATCH (movie:Movie { name: 'Blade Runner' })

OPTIONAL MATCH (movie)-[:WRITTEN_BY|BASED_ON]->(entity)
    WHERE entity:Person OR entity:Novel

OPTIONAL MATCH (entity:Novel)-[:WRITTEN_BY]->(sourceNovelWriter:Person)

RETURN sourceNovelWriter

结果符合预期(即它们反映了菲利普·K·迪克作为《银翼杀手》的源小说作家):

╒═══════════════════════════════════╕
│"sourceNovelWriter"                │
╞═══════════════════════════════════╡
│{"name":"Philip K Dick","id":"103"}│
├───────────────────────────────────┤
│null                               │
└───────────────────────────────────┘

然后为带有Novel 标签的节点创建name 属性的索引:

CREATE INDEX ON :Novel(name)

然后为带有Novel 标签的节点创建name 属性存在的约束:

CREATE CONSTRAINT ON (n:Novel) ASSERT EXISTS(n.name)

注意以下行为仅在同时应用索引和约束时才会出现;如果只应用一个,则不会发生。

重新运行初始查询显示结果已更改为如下所示,并且不是预期的(即他们错误地指出 W P Kinsella 是 Blade Runner 的源小说作家):

╒═══════════════════════════════════╕
│"sourceNovelWriter"                │
╞═══════════════════════════════════╡
│{"name":"Philip K Dick","id":"103"}│
├───────────────────────────────────┤
│{"name":"W P Kinsella","id":"203"} │
├───────────────────────────────────┤
│{"name":"Philip K Dick","id":"103"}│
├───────────────────────────────────┤
│{"name":"W P Kinsella","id":"203"} │
└───────────────────────────────────┘

可以通过从第二个OPTIONAL MATCH 中删除Novel 标签来修复查询(但最好是明确表示仅当entity 变量具有@987654335 时才需要匹配@标签):

MATCH (movie:Movie { name: 'Blade Runner' })

OPTIONAL MATCH (movie)-[:WRITTEN_BY|BASED_ON]->(entity)
    WHERE entity:Person OR entity:Novel

OPTIONAL MATCH (entity)-[:WRITTEN_BY]->(sourceNovelWriter:Person)

RETURN sourceNovelWriter

这会返回:

╒═══════════════════════════════════╕
│"sourceNovelWriter"                │
╞═══════════════════════════════════╡
│{"name":"Philip K Dick","id":"103"}│
├───────────────────────────────────┤
│null                               │
└───────────────────────────────────┘

entity 变量可以通过修改查询使其成为返回值来检查:

MATCH (movie:Movie { name: 'Blade Runner' })

OPTIONAL MATCH (movie)-[:WRITTEN_BY|BASED_ON]->(entity)
    WHERE entity:Person OR entity:Novel

OPTIONAL MATCH (entity:Novel)-[:WRITTEN_BY]->(sourceNovelWriter:Person)

RETURN entity

这错误地在结果中包含Shoeless Joe

╒══════════════════════════════════════════════════════════╕
│"entity"                                                  │
╞══════════════════════════════════════════════════════════╡
│{"name":"Do Androids Dream of Electric Sheep?","id":"102"}│
├──────────────────────────────────────────────────────────┤
│{"name":"Shoeless Joe","id":"202"}                        │
├──────────────────────────────────────────────────────────┤
│{"name":"Do Androids Dream of Electric Sheep?","id":"102"}│
├──────────────────────────────────────────────────────────┤
│{"name":"Shoeless Joe","id":"202"}                        │
└──────────────────────────────────────────────────────────┘

如果第二个OPTIONAL MATCH被删除,即

MATCH (movie:Movie { name: 'Blade Runner' })

OPTIONAL MATCH (movie)-[:WRITTEN_BY|BASED_ON]->(entity)
    WHERE entity:Person OR entity:Novel

RETURN entity

那么返回的entity 与 Blade Runner 正确相关:

╒══════════════════════════════════════════════════════════╕
│"entity"                                                  │
╞══════════════════════════════════════════════════════════╡
│{"name":"Do Androids Dream of Electric Sheep?","id":"102"}│
├──────────────────────────────────────────────────────────┤
│{"name":"Hampton Fancher","id":"100"}                     │
└──────────────────────────────────────────────────────────┘

似乎entity 变量在第二个OPTIONAL MATCH 中被重置,但只有在同时设置了索引和约束时。

这是预期的吗?是什么导致了这种行为?

提前致谢。

【问题讨论】:

    标签: neo4j cypher constraints database-indexes


    【解决方案1】:

    是的,这很好地说明了 Neo4j 4.2.3 中已修复的错误,并且当标签出现在先前绑定的变量的 OPTIONAL MATCH 中时会发生。

    来自更新日志:

    修复了使用索引扫描来错误地解决 OPTIONAL MATCH 的错误。

    https://github.com/neo4j/neo4j/wiki/Neo4j-4.2-changelog#423

    修复之前的解决方法是删除冗余标签。

    我们强烈建议您至少更新到您的次要版本的最新补丁,以避免已知和已修复的错误。

    【讨论】:

    • 非常感谢 - 我已经升级到 Neo4j v4.2.7,一切都很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多