Cypher查询以搜索所有属性中的短语

Yar*_*mer 5 neo4j cypher

我在尝试在我的Neo4j数据库中实现搜索时遇到了一个有趣的问题.我想在任何节点的属性中搜索某个短语(也允许部分匹配).这必须是通用的,适用于所有节点类型和标签,因此我无法预先定义要搜索的属性列表.

为了理解这个问题,请考虑Neo4j浏览器(:play movie graph)中捆绑的着名Movie DB教程:假设我想搜索标签Movie中具有以'The'开头的属性的节点.我的第一个想法是:

match (m:Movie)
where (any(prop in keys(m) where m[prop] starts with "The")) 
return m
Run Code Online (Sandbox Code Playgroud)

这当然会抛出错误,因为其中一个属性是数字而不是字符串.使用toString对我没用,因为在我的DB中,一些属性是布尔值,而布尔值没有响应toString.

我的下一次尝试是使用正则表达式,这对于搜索也更好,因为我可以使它不区分大小写并且通常更健壮.所以我这样做了:

match (m:Movie)
where (any(prop in keys(m) where m[prop] =~ "(?i)The .*"))
return m
Run Code Online (Sandbox Code Playgroud)

它奏效了!我得到了他们的标题或标语以"The"开头的所有电影.有很多的欣喜.

但现在是棘手的部分.我的搜索还需要提供对搜索的否定,即所有没有任何以"The"开头的属性的电影.我显然试过了:

match (m:Movie)
where NOT (any(prop in keys(m) where m[prop] =~ "(?i)The .*"))
return m
Run Code Online (Sandbox Code Playgroud)

但是这个查询返回了一个空响应.没有错误,只是没有结果.

在尝试隔离问题时,我意识到查询在以下情况下确实有效:

  1. 如果节点只有字符串属性(没有数字或布尔值).
  2. 如果我使用完全匹配而不是regex(where NOT(any(prop in keys(m) where m[prop] = "Hoffa"))).
  3. 如果我搜索特定的属性(where NOT(any(prop in ['title','tagline'] where m[prop] =~ "(?i)The .*")))

似乎只有组合not,any和正则表达式打破了查询,我在寻找故障原因丢失.

cyb*_*sam 5

至少在 neo4j 3.0 中,STARTS WITH语法似乎更适合您的场景(但区分大小写):

MATCH (m:Movie)
WHERE NONE(prop in keys(m) where TOSTRING(m[prop]) STARTS WITH "The ")
RETURN m;
Run Code Online (Sandbox Code Playgroud)