知识库

关于 OPTIONAL MATCH 的说明

一个 OPTIONAL MATCH 会像 MATCH 一样,在您的图数据库中匹配模式。不同之处在于,如果没有找到匹配项,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(es)。您应该 MATCH 那些必须存在的部分,然后对模式中可能不存在的部分使用 OPTIONAL MATCH(es)。

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

© . All rights reserved.