Neo4j:应用索引和约束更改查询结果
Neo4j: Applying index and constraint changes query results
我遇到了 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
结果符合预期(即它们反映了 Philip K Dick 作为 Blade 运行ner 的源小说作家):
╒═══════════════════════════════════╕
│"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)
N.B。以下行为仅在同时应用索引和约束时才会出现;如果只应用一个,则不会发生。
Re-运行 初始查询显示结果已更改为如下所示,这不是预期的(即他们错误地指出 W P Kinsella 是 Blade 运行 的源小说作者内尔):
╒═══════════════════════════════════╕
│"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
变量有一个 Novel
标签):
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
这个returns:
╒═══════════════════════════════════╕
│"sourceNovelWriter" │
╞═══════════════════════════════════╡
│{"name":"Philip K Dick","id":"103"}│
├───────────────────────────────────┤
│null │
└───────────────────────────────────┘
可以通过修改查询使其成为 return 值来检查 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
然后 returned entity
正确地与 Blade 运行ner:
╒══════════════════════════════════════════════════════════╕
│"entity" │
╞══════════════════════════════════════════════════════════╡
│{"name":"Do Androids Dream of Electric Sheep?","id":"102"}│
├──────────────────────────────────────────────────────────┤
│{"name":"Hampton Fancher","id":"100"} │
└──────────────────────────────────────────────────────────┘
似乎 entity
变量在第二个 OPTIONAL MATCH
中重置,但只有在设置索引和约束条件时才重置。
这是预料之中的吗?是什么导致了这种行为?
提前致谢。
是的,这是对 Neo4j 4.2.3 中修复的错误的一个很好的说明,当标签出现在先前绑定变量的可选匹配中时会发生。
来自更新日志:
Fixed a bug where an index scan would be used to solve an OPTIONAL MATCH incorrectly.
https://github.com/neo4j/neo4j/wiki/Neo4j-4.2-changelog#423
修复之前的解决方法是删除冗余标签。
我们强烈建议您至少更新到您的次要版本的最新补丁,以避免已知和已修复的错误。
我遇到了 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
结果符合预期(即它们反映了 Philip K Dick 作为 Blade 运行ner 的源小说作家):
╒═══════════════════════════════════╕
│"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)
N.B。以下行为仅在同时应用索引和约束时才会出现;如果只应用一个,则不会发生。
Re-运行 初始查询显示结果已更改为如下所示,这不是预期的(即他们错误地指出 W P Kinsella 是 Blade 运行 的源小说作者内尔):
╒═══════════════════════════════════╕
│"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
变量有一个 Novel
标签):
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
这个returns:
╒═══════════════════════════════════╕
│"sourceNovelWriter" │
╞═══════════════════════════════════╡
│{"name":"Philip K Dick","id":"103"}│
├───────────────────────────────────┤
│null │
└───────────────────────────────────┘
可以通过修改查询使其成为 return 值来检查 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
然后 returned entity
正确地与 Blade 运行ner:
╒══════════════════════════════════════════════════════════╕
│"entity" │
╞══════════════════════════════════════════════════════════╡
│{"name":"Do Androids Dream of Electric Sheep?","id":"102"}│
├──────────────────────────────────────────────────────────┤
│{"name":"Hampton Fancher","id":"100"} │
└──────────────────────────────────────────────────────────┘
似乎 entity
变量在第二个 OPTIONAL MATCH
中重置,但只有在设置索引和约束条件时才重置。
这是预料之中的吗?是什么导致了这种行为?
提前致谢。
是的,这是对 Neo4j 4.2.3 中修复的错误的一个很好的说明,当标签出现在先前绑定变量的可选匹配中时会发生。
来自更新日志:
Fixed a bug where an index scan would be used to solve an OPTIONAL MATCH incorrectly.
https://github.com/neo4j/neo4j/wiki/Neo4j-4.2-changelog#423
修复之前的解决方法是删除冗余标签。
我们强烈建议您至少更新到您的次要版本的最新补丁,以避免已知和已修复的错误。