原文鏈接:https://neo4j.com/developer/kb/why-where-clause-does-not-filter/
在Cypher語句中,當(dāng)你發(fā)現(xiàn)WHERE沒有起作用時,可以嘗試下面的幾種方法找到問題所在。
檢測WHERE條件是否跟在了OPTIONAL MATCH之后
WHERE語句是不能獨立使用的,它必須配合MATCH、WITH或者 OPTIONAL MATCH一起使用。
當(dāng)“WITH...WHERE"或”MATCH...WHERE"這種查詢語句出現(xiàn)時,WHERE條件會作用到所有結(jié)果集上。通常情況我們期望的是,剔除那些WHERE條件為False的數(shù)據(jù)。
然而“OPTIONAL MATCH ... WHERE”的情況略有不同,這個查詢并不會剔除數(shù)據(jù)。當(dāng)使用OPTIONAL MATCH時,當(dāng)匹配不到數(shù)據(jù)或WHERE條件為False時,這個新引入的變量只會被賦值為null。原來的數(shù)據(jù)并不會剔除,已存在的變量也不會發(fā)生變化,給人的感覺就是WHERE條件沒有起作用,而事實上呢,是WHERE被應(yīng)用到了錯誤的地方。
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年后發(fā)行的電影和參與這些電影的動畫制作人,但是這個查詢是錯誤的。WHERE條件僅僅對OPTIONAL MATCH有作用,所以,所有電影都會被查詢出來,沒有一個會被過濾掉。但是動畫制作人數(shù)據(jù)則返回了參與1999年以后發(fā)行的電影的動畫制作人。
如果要修復(fù)這個查詢語句,只需要將WHERE條件放到合適的位置,將它放到MATCH或WITH后面即可篩選出想要的數(shù)據(jù)了。
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條件子句失效,特別是大小寫問題。
結(jié)點的標(biāo)簽、關(guān)系類型、變量、屬性的鍵和值都是大小寫敏感的,所以一定要確保你寫的是正確的。
MATCH (m:Movie)
WHERE NOT (m)<-[:worked_on]-(a:animator) AND m.ReleaseYear > 1999
RETURN m上面這個查詢語句看上去沒有任何拼寫錯誤,但事實上,他在關(guān)系類型、結(jié)點續(xù)簽以及屬性鍵上大小寫都錯了,所以,這個查詢的WHERE條件是不起作用。
檢測屬性的變量類型
在使用int或float類型的比較失敗時,你可以先確認一下屬性的值是不是int或float類型。
確認方法也很簡單:在neo4j瀏覽器的文本結(jié)果視圖模式下,字符串的值是有引號的,而int或float類型的值是沒有。 在導(dǎo)入數(shù)據(jù)時要特別小心,尤其是CSV文件導(dǎo)入,它會把所有值都轉(zhuǎn)成字符串。所以,為了避免這個問題,你需要使用toInteger()或toFloat()把字符串轉(zhuǎn)成int或float類型。
屬性的鍵或值的首尾空格
屬性的首尾空格有時會造成WHERE條件無效,這一般是由于圖中的數(shù)據(jù)問題而不是查詢的問題。
MATCH (m:Movie)<-[:ACTED_IN]-(p:Person)
WHERE p.name = 'Keanu Reeves'
RETURN m上面的查詢語句看上去沒啥問題,但事實上,結(jié)點的name屬性是“Keanu Reeves ”,在結(jié)尾有一個空格,所以,這個查詢語句是查不到這個結(jié)點的。
通常情況,只能仔細檢測結(jié)點和關(guān)系上的字符串值,看是否有空格。如果使用Neo4j瀏覽器,文本結(jié)果視圖可以很容易發(fā)現(xiàn)空格。另外,查詢時使用 STARTS WITH, ENDS WITH, 或 CONTAINS 這幾個函數(shù)也可以幫助你判斷屬性值是否有空格。
屬性的值里存在空格的情況較少,如果有,一般都是因為從錯誤格式的文件中導(dǎo)入造成的。
例如,嘗試導(dǎo)入一下CSV文件的標(biāo)題行:?
nickName, firstName,lastName 在firstName的開頭一個空格,在lastName的結(jié)尾有一個空格。導(dǎo)入時,屬性鍵就會包含首部空格和尾部空格,因此實際的屬性鍵就變成了“nickName”、” firstName”和“l(fā)astName “,如果沒有檢查出來,那么查詢時就會出問題了。