知识库

为什么我的 WHERE 子句不起作用?

当 WHERE 子句似乎不起作用时,这会令人沮丧。可以使用以下方法来找出问题所在。

检查 OPTIONAL MATCH 后的 WHERE 子句

WHERE 子句不能单独使用,它们总是与 MATCH、WITH 或 OPTIONAL MATCH 配对,并且正是这种配对决定了当 WHERE 子句的结果为 false 时的行为。

WITH …​ WHEREMATCH …​ WHERE 会将 WHERE 子句应用于所有结果行,这通常也是大多数用户期望的 WHERE 行为——当 WHERE 为 false 时删除对应的行。

然而,OPTIONAL MATCH …​ WHERE 的行为不同,因为 OPTIONAL MATCH 永远不会删除行。使用 OPTIONAL MATCH 时,如果给定的模式不匹配,或其 WHERE 子句的结果为 false,则该模式中新引入的变量在当前行上会变为 null。行永远不会被删除,已有的变量保持不变,这会给人一种 WHERE 子句根本没有起作用的错觉,实际问题在于它被错误地应用到了不该应用的地方。

MATCH (m:Movie)
OPTIONAL MATCH (m)<-[:WORKED_ON]-(a:Animator)
WHERE m.releaseYear > 1999 AND a IS NOT NULL
RETURN m, collect(a) as animators

在上面的例子中,看起来像是查询 1999 年以后上映的电影以及这些电影的动画师,但这并不准确。WHERE 子句只会影响 OPTIONAL MATCH,因此所有电影都会被返回,均不会被过滤掉,只是动画师集合只会在 1999 年以后上映的电影上被填充。

要修复该查询,需要把 WHERE 移动到其他位置,使其与 MATCH 或 WITH 关联,从而在需要时过滤掉行。

MATCH (m:Movie)
OPTIONAL MATCH (m)<-[:WORKED_ON]-(a:Animator)
WITH m, a
WHERE m.releaseYear > 1999 AND a IS NOT NULL
RETURN m, collect(a) as animators

检查 WHERE 子句中的拼写错误或大小写不匹配

拼写错误和写错的元素很容易导致 WHERE 子句失效,这其中也包括大小写不匹配。

节点标签、关系类型、变量以及属性键和值都区分大小写,请确保在大小写上保持一致且正确。

MATCH (m:Movie)
WHERE NOT (m)<-[:worked_on]-(a:animator) AND m.ReleaseYear > 1999
RETURN m

上述查询没有拼写错误,但关系类型、节点标签和属性键的大小写与图中实际存储的不一致,这会显著影响 WHERE 子句的效果。

检查假定的数值属性是否实际上是字符串

当数值比较或匹配似乎失效时,最好确认你正在比较的属性确实是数字。

在文本结果视图中,字符串值会带引号,而数值则不会。

导入时要格外留意,尤其是 CSV 导入,因为所有值默认都会被解释为字符串。需要使用 toInteger()toFloat() 将字符串转换为数值,以避免此类问题。

检查属性键和值中的前导或尾随空格

属性中的前导或尾随空格会让 WHERE 子句看起来像是失效了,这通常是图中数据本身的问题,而非查询本身的错误。

MATCH (m:Movie)<-[:ACTED_IN]-(p:Person)
WHERE p.name = 'Keanu Reeves'
RETURN m

上述查询看起来没有问题,甚至可能完全正确。但如果节点的 name 属性实际上是 "Keanu Reeves "(末尾有空格),查询就会失效。

通常建议再次确认节点和关系上预期的字符串值,看看是否有意外的空格。如果使用 Neo4j 浏览器,文本结果视图通常是最方便检测额外空格的方式。使用 STARTS WITHENDS WITHCONTAINS 进行查询也能帮助检验属性值的假设。

属性键中的额外空格比较少见,但确实会发生,例如从格式错误的文件导入数据时。

例如,如果我们尝试导入以下标题的 CSV 文件:

nickName, firstName,lastName

firstName 前有一些前导空格,在 lastName 后有尾随空格。导入后,属性键本身会包含这些空格,实际的属性键会变成 "nickName"、" firstName" 和 "lastName ",如果没有被发现,就会很快成为混淆的来源。

© . This site is unofficial and not affiliated with Neo4j, Inc.