我想要得到的是具有任何属性名称(键)的某些属性值,而没有任何属性其他值的节点。
简而言之,伪Google查询如下:
+Tom +val1 +val2 (...) -Cruise -valX -valY (...)
和Cypher查询类似:
MATCH (n) WHERE (
ANY ( p in KEYS(n) WHERE n[p] CONTAINS 'Tom' ) AND
NONE ( p in KEYS(n) WHERE n[p] CONTAINS 'Cruise')
)
RETURN n
但是电影数据库(:play电影图)的测试结果只是一个空列表,而数据库中还有其他名为“ Tom”的演员,例如汤姆·汉克斯。 (匹配(n),其中(any(KEYS(n)中的p,其中n [p]包含'Tom'))返回n 给[汤姆·泰克维尔,汤姆·汉克斯,汤姆·克鲁斯,汤姆·斯凯里特])
所以我尝试使用'om'而不是'Tom',这一次,结果是'om'的不完整列表:
match (n) where (
any( p in KEYS(n) WHERE n[p] contains 'om') and
none( p in Keys(n) WHERE n[p] contains 'Cruise')
)
return n
给予
[Romantic (genre), Naomie Harris, James Thompson, Jessica Thompson]
(No Tom's -- why?)
也尝试用NOT ANY()代替NONE()并得到相同的结果。
这种不一致是从哪里来的?
答案 0 :(得分:3)
问题在于节点的属性类型不是string
。对于他们来说,NONE验证给出了null
,这完全给了where
一个错误。例如,此查询不返回任何内容:
WITH {k1: 1, k2: '2'} AS test
WHERE NONE(key IN keys(test) WHERE test[key] CONTAINS '1')
RETURN test
因此,在这种情况下,您需要检查属性的类型。由于没有本机类型检查功能,因此可以使用APOC library
中的功能:
MATCH (n) WHERE (
ANY(p in KEYS(n) WHERE apoc.meta.cypher.type(n[p]) = 'STRING' AND n[p] CONTAINS 'Tom') AND
NONE(p in KEYS(n) WHERE apoc.meta.cypher.type(n[p]) = 'STRING' AND n[p] CONTAINS 'Cruise')
)
RETURN n
答案 1 :(得分:3)
@ stdob--提供了对该问题的准确解释。
但是有更简单的解决方法。例如,您可以使用COALESCE function()强制将NULL
的值视为FALSE
:
MATCH (n)
WHERE
ANY ( p in KEYS(n) WHERE n[p] CONTAINS 'Tom' ) AND
NONE( p in KEYS(n) WHERE COALESCE(n[p] CONTAINS 'Cruise', FALSE))
RETURN n