理解不存在的属性和处理空值
在 Neo4j 中,由于没有表模式或类似的机制来限制可能的属性,因此节点和关系属性的“不存在”和“空”是等价的。也就是说,实际上不存在具有空值的属性;空表示该属性根本不存在。
这与具有表模式的关系型数据库形成对比,在关系型数据库中,即使某个列的值为空,该列也存在于表的每一行中。
例如,如果我们有一个 :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
NULL 映射值
这也表明,尽管节点和关系属性的“不存在”和“空”是等价的,但这对于映射或集合并不适用。如上所示,具有空值的映射条目与缺少该条目的映射是不同的。
这种区别在使用映射投影时尤其有用。映射投影是节点属性的映射视图,可用于强制显示返回数据中的属性,即使该属性在该节点上不存在。
例如,在此查询中,返回的节点数据中的 email 属性可能会也可能不会返回,具体取决于该属性是否存在于每个返回的节点上
MATCH (p:Person)
RETURN p
但是,如果希望 email 属性始终显示,如果属性不存在则显示 NULL,则可以使用如下所示的映射投影
MATCH (p:Person)
RETURN p {.*, .email}
NULL 列表值
列表中也允许使用 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
与之前忽略空值不同,我们看到列表中包含了“未设置”。
MATCH (p:Person)
WHERE COALESCE(p.optedIn, false) <> true
RETURN p
使用 COALESCE(),我们可以将空值视为比较目的下的不同值。请注意,对空值的相等或不相等比较,例如 null <> true
,会返回空值,而不是布尔值,因此 COALESCE() 在这里特别有用。
MATCH (p:Person)
RETURN COALESCE(p.email, p.backupEmail, p.backupBackupEmail, 'NOT SET') as email
允许使用多个回退,将使用第一个非空值。
使用 NULL 进行匹配和合并
虽然可以在 MATCH 中执行节点变量为空的操作(例如来自失败的 OPTIONAL MATCH),但不能使用空节点变量创建或合并模式。
当没有 :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
此页面是否有帮助?