我尝试在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
这当然会抛出错误,因为其中一个属性是数字而不是字符串。使用toString
对我没用,因为在我的数据库中,一些属性是布尔值,而布尔值不响应toString
。
我的下一次尝试是使用正则表达式,这对于搜索也更好,因为我可以使它不区分大小写并且通常更健壮。所以我这样做了:
match (m:Movie)
where (any(prop in keys(m) where m[prop] =~ "(?i)The .*"))
return m
它有效!我得到了他们的标题或标语以“The”开头的所有电影。并且非常高兴。
但现在是棘手的部分。我的搜索还需要提供对搜索的否定,即所有不的电影都具有以'The'开头的任何属性。我显然试过了:
match (m:Movie)
where NOT (any(prop in keys(m) where m[prop] =~ "(?i)The .*"))
return m
但是这个查询返回了一个空响应。没有错误,只是没有结果。
在尝试隔离问题时,我意识到查询 在以下情况下有效:
where NOT(any(prop in keys(m) where m[prop] = "Hoffa"))
)。where NOT(any(prop in ['title','tagline'] where m[prop] =~ "(?i)The .*"))
)似乎只有not
,any
和正则表达式的组合打破了查询,而我却迷失了为什么会发生这种情况。
答案 0 :(得分:4)
至少在neo4j 3.0中,STARTS WITH
语法似乎更适合您的场景(但它区分大小写):
MATCH (m:Movie)
WHERE NONE(prop in keys(m) where TOSTRING(m[prop]) STARTS WITH "The ")
RETURN m;
答案 1 :(得分:1)
而不是使用
NOT (ANY
尝试
(NONE
答案 2 :(得分:0)
这对我有用
match (m:Movie)
where (any(prop in keys(m) where m[prop] =~ '.*the.*'))
return m