Neo4j知识库:Cypher查询语句中为什么WHERE条件没起
原文链接:https://neo4j.com/developer/kb/why-where-clause-does-not-filter/
在Cypher语句中,当你发现WHERE没有起作用时,可以尝试下面的几种方法找到问题所在。
检测WHERE条件是否跟在了OPTIONAL MATCH之后
WHERE语句是不能独立使用的,它必须配合MATCH、WITH或者 OPTIONAL MATCH一起使用。
当“WITH...WHERE"或”MATCH...WHERE"这种查询语句出现时,WHERE条件会作用到所有结果集上。通常情况我们期望的是,剔除那些WHERE条件为False的数据。
然而“OPTIONAL MATCH ... WHERE”的情况略有不同,这个查询并不会剔除数据。当使用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
检查WHER条件的拼写错误或大小写
拼写错误很容易造成WHERE条件子句失效,特别是大小写问题。
结点的标签、关系类型、变量、属性的键和值都是大小写敏感的,所以一定要确保你写的是正确的。
MATCH (m:Movie)
WHERE NOT (m)<-[:worked_on]-(a:animator) AND m.ReleaseYear > 1999
RETURN m
上面这个查询语句看上去没有任何拼写错误,但事实上,他在关系类型、结点续签以及属性键上大小写都错了,所以,这个查询的WHERE条件是不起作用。
检测属性的变量类型
在使用int或float类型的比较失败时,你可以先确认一下属性的值是不是int或float类型。
确认方法也很简单:在neo4j浏览器的文本结果视图模式下,字符串的值是有引号的,而int或float类型的值是没有。 在导入数据时要特别小心,尤其是CSV文件导入,它会把所有值都转成字符串。所以,为了避免这个问题,你需要使用toInteger()或toFloat()把字符串转成int或float类型。
属性的键或值的首尾空格
属性的首尾空格有时会造成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 “,如果没有检查出来,那么查询时就会出问题了。