知识库

为什么我的 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 ",如果未检测到,可能会很快成为混乱的来源。