为什么Cypher WHERE不起作用?
【翻译自:https://neo4j.com/developer/kb/why-where-clause-does-not-filter/
】
【由Neo4j APAC授权编译发布】
当我们在写Neo4j Cyper查询语句时,偶尔会发现 WHERE 子句似乎不起作用时,可能会感到非常沮丧,您可以使用下面这些方法找出问题所在。
1、检查OPTIONAL MATCH之后的WHERE子句
WHERE 子句不能单独使用,它们始终与MATCH、WITH或OPTIONAL MATCH配对,并且此配对定义了 WHERE 子句执行为 false 时的行为。
对于 WITH … WHERE 和 MATCH … WHERE,我们期望 WHERE 子句应用于所有结果行,而当 WHERE 的值为 false 时则过滤行。
但是,OPTIONAL MATCH … WHERE其行为有所不同,因为OPTIONAL MATCH不会删除行。使用OPTIONAL MATCH时,如果给定的模式不匹配,或者其WHERE子句的值为false,则模式中新引入的变量对于给定的行将为null。从不删除行,并且现有变量保持不变,当真正的问题是将WHERE子句应用于错误的事务时,我们会觉得 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
2、WHERE子句中检查拼写错误或大小写不匹配
WHERE子句中错字和拼写错误很容易抛出,包括不匹配。
节点标签、关系类型、变量以及属性键和值都区分大小写,因此请确保前后一致并正确无误。
MATCH (m:Movie)
WHERE NOT (m)<-[:worked_on]-(a:animator) AND m.ReleaseYear > 1999
RETURN m
上面的查询没有任何拼写错误,但是关系类型、节点标签和属性键的大小写与图中的实际情况有所不同。
3、检查应为数值的属性是否存为字符串
在数值比较或匹配失败的情况下,要确保比较的属性是否为数值。
在文本结果视图中,字符串值将用引号引起来,而数值将没有。
在导入过程中,尤其是在CSV导入过程中,请特别注意,因为所有值都被解释为字符串。您需要使用 toInteger() 或 toFloat() 将字符串转换为数值,以避免出现此问题。
4、检查属性键和值中是否存在空格
属性存在空格会使 WHERE 子句看起来不起作用,通常是图数据而不是查询本身的问题。
MATCH (m:Movie)<-[:ACTED_IN]-(p:Person)
WHERE p.name = 'Keanu Reeves'
RETURN m
上面的查询看起来不错,并且可能是完全正确的。但是,如果节点的 name 属性存在空格“ Keanu Reeves”,则该查询将不起作用。
仔细检查节点和关系上的预期字符串值以查看是否存在意外的空格,如果使用Neo4j 浏览器,则文本结果视图通常是轻松检测多余空格的最佳方法。使用STARTS WITH、ENDS WITH或CONTAINS进行查询,可以帮助测试属性值。
属性键中多余的空格很少,但是偶尔会发生,例如从格式错误的文件导入数据时。
例如,如果我们尝试导入具有以下标头的csv文件:
“nickName, firstName,lastName ”
firstName前有空格,lastName后面有空格。导入后,属性键本身将包含空格,因此实际的属性键将变为“nickName”、“ firstName”和“lastName ”,如果没有被发现,可能很快会引起混乱。