知识库

理解不存在的属性并处理空值

在 Neo4j 中,由于没有表模式或等效机制来限制可能的属性,节点和关系属性的不存在与空值是等效的。也就是说,实际上不存在值为 null 的属性;null 表示该属性根本不存在。

这与具有表模式的关系型数据库形成对比,在关系型数据库中,即使某列的值为 null,该列的字段在表行中也存在。

例如,如果我们有一个由 :Person 节点组成的图,以下两个查询被认为是相同的

MATCH (p:Person)
WHERE p.id = $personId
RETURN NOT EXISTS(p.email)
MATCH (p:Person)
WHERE p.id = $personId
RETURN p.email IS NULL

无论所讨论的属性是用于其他节点(仅在此节点上缺失),还是图中一个无意义或从未使用过的属性(例如 p.pinkElephant),都无关紧要。如果属性不存在,则如上所示的 NULL 检查将返回 true。

同样,以下两个查询会导致属性被移除

MATCH (p:Person)
WHERE p.id = $personId
SET p.email = null
MATCH (p:Person)
WHERE p.id = $personId
REMOVE p.email

如果您需要一种动态地从节点中清除多个属性的方法,使用映射来更新节点属性时,这会很有用。

WITH {email:null, dob:null} as clearProps
MATCH (p:Person)
WHERE p.id = $personId
SET p += clearProps

空值映射

这也表明,尽管节点和关系属性的不存在与空值是等效的,但对于映射或集合来说并非如此。如上所示,包含空值条目的映射与缺少该条目的映射是不同的。

这种区分在使用映射投影时特别有用。映射投影是节点属性的映射视图,即使该属性不存在于节点上,也可以用于强制显示返回数据中的某个属性。

例如,在此查询中,返回的节点数据中的 email 属性可能会也可能不会返回,这取决于该属性是否存在于每个返回的节点上

MATCH (p:Person)
RETURN p

但是,如果我们希望 email 属性始终显示,并在属性不存在时显示 NULL,我们可以使用映射投影,如下所示

MATCH (p:Person)
RETURN p {.*, .email}

空值列表

NULL 值也允许出现在列表中

RETURN [1,2,3,null,5]

然而,对节点或关系属性进行聚合时会跳过或忽略空值

MATCH (p:Person)
RETURN count(p.email) as emailCount

计数不包含空值。

MATCH (p:Person)
RETURN collect(p.email) as emails

这会跳过空值;返回的集合不包含任何空值。

在逻辑表达式及其他上下文中处理 NULL

Neo4j 开发者手册中有一个关于 处理 NULL 的详细章节,并说明了表达式何时会返回 NULL。

使用 COALESCE() 为空值指定默认值

在某些情况下,当节点或关系上不存在属性时,我们可能希望显示一个备用默认值。或者我们可能希望对可能为空的值执行相等或不相等比较,并在值为空时使用默认值。

COALESCE() 允许处理这些情况。它接受任意数量的参数,并返回遇到的第一个非空值。

MATCH (p:Person)
RETURN collect(COALESCE(p.email, 'NOT SET')) as emails

我们看到列表包含了 'NOT SET',而不是像之前那样忽略空值。

MATCH (p:Person)
WHERE COALESCE(p.optedIn, false) <> true
RETURN p

使用 COALESCE(),我们可以将空值视为不同的值进行比较。请注意,与空值进行的相等或不相等比较(例如 null <> true)结果为 null,而不是布尔值,因此 COALESCE() 在这里特别有用。

MATCH (p:Person)
RETURN COALESCE(p.email, p.backupEmail, p.backupBackupEmail, 'NOT SET') as email

允许使用多个备用值,将使用第一个非空值。

使用 NULL 进行匹配和合并

空节点变量

虽然您可以执行 MATCH 查询,其中匹配中的节点变量为 null(例如来自失败的 OPTIONAL MATCH),但不能使用空节点变量来 CREATE 或 MERGE 模式。

当没有 :PinkElephant 节点时,这有效,但不会返回记录

OPTIONAL MATCH (node1:PinkElephant)
WITH node1
MATCH (node1)-[:ACTED_IN]->(m:Movie)
RETURN node1

然而,以下两者都会抛出错误

OPTIONAL MATCH (node1:PinkElephant)
WITH node1
MERGE (node1)-[:ACTED_IN]->(m:Movie)
RETURN node1

OPTIONAL MATCH (node1:PinkElephant)
WITH node1
CREATE (node1)-[:ACTED_IN]->(m:Movie)
RETURN node1
空属性值

当我们使用空属性值时,我们可以使用空属性值进行 MATCH 或 CREATE,但不能使用 MERGE

这些有效

OPTIONAL MATCH (ele:PinkElephant)
WITH ele
MATCH (node1:Person {name:ele.name})-[:ACTED_IN]->(m:Movie)
RETURN node1

OPTIONAL MATCH (ele:PinkElephant)
WITH ele
CREATE (node1:Person {name:ele.name})-[:ACTED_IN]->(m:Movie)
RETURN node1

但这会抛出错误

OPTIONAL MATCH (ele:PinkElephant)
WITH ele
MERGE (node1:Person {name:ele.name})-[:ACTED_IN]->(m:Movie)
RETURN node1
© . All rights reserved.