【发布时间】: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