使用Neo4j全文索引进行包含查询

时间:2019-02-20 01:11:47

标签: neo4j lucene cypher

我正在使用neo4j 3.5,大约有900万个用户节点。我试图实现以下查询,但是时间太长了:

  

MATCH(用户:User)在哪里(users.username包含“ joe”或users.first_name CONTAINS“ joe”或users.last_name包含“ joe”)   RETURN用户   LIMIT 30

我希望通过创建以下索引来利用neo4j 3.5的newe全文索引功能:

CALL db.index.fulltext.createNodeIndex('users', ['User'], ['username', 'first_name', 'last_name'])

然后像这样查询数据库

CALL db.index.fulltext.queryNodes('users', joe)
YIELD node
RETURN node.user_id

我认为这将与包含并返回其用户名,first_name或last_name包含joe的用户(例如:myjoe12,joe12、12joe,44joeseph等)相同,但是似乎返回的字段为{{1 }}正好或包含由空格分隔的joe(例如:Joe B,Joe y1),我尝试在查询中使用joe,但是只返回以joe*开头的所有内容返回包含joe或任何搜索词的所有内容。最好的方法是什么?

2 个答案:

答案 0 :(得分:0)

速度问题/索引:

到目前为止,我知道Neo4j的STARTS WITHENDS WITH的优化索引仅适用于非复合索引。

如果我阅读此docs paragraph,我的结论将是:您的900万用户将被一个一个地搜索,neo4j不会在您的查询中使用任何索引。是什么让这个查询真的很慢。

您的问题的答案:

  

我想返回包含Joe或任何搜索词的所有内容。

您可能正在寻找正则表达式搜索(这也很慢,并且不建议使用索引搜索):

基于您的查询的示例查询:

MATCH (users:User)
WHERE (users.username =~ "(?i).*joe.*" OR users.first_name =~ "(?i).*joe.*" OR users.last_name =~ "(?i).*joe.*")
RETURN users
LIMIT 30

(?i)的解释意味着不区分大小写,因此将匹配Joejoe。参见regex operator docsregex where docs

答案 1 :(得分:0)

对于全文模式索引,您似乎需要在查询中使用模糊搜索运算符~,尽管您可能需要对得分进行一些过滤以确保您正在查看相关结果:

CALL db.index.fulltext.queryNodes('users', 'joe~')
YIELD node, score
WHERE score > .8
RETURN node.user_id