知识库

关于 OPTIONAL MATCH 的说明

OPTIONAL MATCHMATCH 一样,用于对图数据库匹配模式。区别在于,如果未找到匹配项,OPTIONAL MATCH 将对模式中缺少的部分使用 null。OPTIONAL MATCH 可以被认为是 Cypher 中 SQL 外连接的等价物。

了解这一点,就可以编写如下 Cypher 查询

OPTIONAL MATCH (actor:Actor)-[:ACTED_IN]->(:Movie)<-[:DIRECTED]-(director:Director {uuid:'fd787f45-df1a-4f8b-b4a9-ab7b90fefae4'})
OPTIONAL MATCH (director)-[:HAS_STUDIO*2]->(:Studio)-[:HAS_ACTOR]->(actor)-[:HAS_PROFILE]->(profile:Profile)
WHERE profile.type IN ["Drama", "Action"]
MERGE (director)-[:HAS]->(actor)
ON CREATE SET profile.uuid = apoc.create.uuid(), profile.lastTimeReported = '2018-12-15T23:13:22.274', profile.reportingState = 'Active'
ON MATCH SET profile.lastTimeReported = '2018-07-15T23:30:00.000', profile.reportingState = 'Active'
RETURN COUNT(profile) as updatedCount

但是,此查询可能会返回以下错误

Neo.DatabaseError.General.UnknownError: org.neo4j.values.storable.NoValue cannot be cast to org.neo4j.values.virtual.VirtualNodeValue

(3.4.5 之前)

Neo.DatabaseError.Statement.ExecutionFailed: Expected to find a node at ref slot 0 but found instead: null

(3.4.5 之后)

这是因为在空数据库上运行以下最简单的查询形式时,以 OPTIONAL MATCH 开头的查询并不总是与 Neo4j 良好配合,特别是在 OPTIONAL MATCH 返回无值并影响查询计划的其余部分时。

OPTIONAL MATCH (a)
MERGE (a)-[:X]->()

这些情况下抛出的消息如下

Expected to find a node at $name but found instead: null
Expected to find a node at $name but found instead: $x
Expected to find a node at $name but found instead: null

遇到这些消息之一时,问题与可选匹配相关,可以通过以普通的 MATCH 开头来解决,例如

MATCH (actor:Actor)-[:ACTED_IN]->(:Movie)<-[:DIRECTED]-(director:Director {uuid:'fd787f45-df1a-4f8b-b4a9-ab7b90fefae4'})
OPTIONAL MATCH (director)-[:HAS_STUDIO*2]->(:Studio)-[:HAS_ACTOR]->(actor)-[:HAS_PROFILE]->(profile:Profile)
WHERE profile.type IN ["Drama", "Action"]
MERGE (director)-[:HAS]->(actor)
ON CREATE SET profile.uuid = apoc.create.uuid(), profile.lastTimeReported = '2018-12-15T23:13:22.274', profile.reportingState = 'Active'
ON MATCH SET profile.lastTimeReported = '2018-07-15T23:30:00.000', profile.reportingState = 'Active'
RETURN COUNT(profile) as updatedCount

如果您的 OPTIONAL MATCH 很长,我们建议您将其分解,以便将其转换为至少一个 MATCH 后跟 OPTIONAL MATCH。您应该 MATCH 必须存在的那些部分,然后在可能不存在的模式部分上使用 OPTIONAL MATCH

对于上面的示例,第一行中的完整模式是必需的,因为我们至少需要导演及其演员。在其他情况下,可能只需要一个起始节点作为最小值。经验法则是从 MATCH 开始尝试捕获所需的图的最小部分,然后在任何其他可选内容上使用 OPTIONAL MATCH