具有多个FuzzyQuery的Lucene BooleanQuery太慢了

时间:2017-10-11 10:51:40

标签: java lucene

Document是公司的员工数据,其中包含多个字段名称:empName, empId, departmentId etc

使用自定义分析器已经索引了大约400万个数据。

搜索查询包含list of employees' name,并且知道列表中的所有员工都属于同一个部门。公司有多个部门。

所以我想为所有员工做fuzzy search'给定department id下的名称。

为此,我使用布尔查询,如下所示:

Query termQuery = new TermQuery(new Term("departmentId","1234"));
BooleanQuery.Builder bld = new BooleanQuery.Builder();
for(String str:employeeNameList) {
    bld.add(new FuzzyQuery(new Term("name",str)), BooleanClause.Occur.SHOULD);
 }       
BooleanQuery bq = bld.build();
BooleanQuery finalBooleanQuery = new BooleanQuery.Builder()
                .add(termQuery, BooleanClause.Occur.MUST)
                .add(bq, BooleanClause.Occur.MUST).build();

现在在finalBooleanQuery search方法内传递IndexSearcher并获得结果。

问题是花费太多时间,当employeeNameList more than 50的大小需要大约500 ms进行搜索时。

如何将时间从500 ms减少到50 ms

这个问题还有其他解决办法吗?

1 个答案:

答案 0 :(得分:2)

如果您查看FuzzyQuery的其他构造函数,您会看到一些简单的方法来提高性能。每个额外的参数都是为了减少FuzzyQuery要做的工作量,从而提高性能。

首先,也是最重要的:

  • 前缀长度:我强烈建议将此值设置为非零值。这是术语开头的多少个字符将进行模糊匹配。所以,如果搜索" abc"前缀为1," abb"和" acc"会匹配,但不会" bbc"。这允许lucene在尝试查找匹配的术语时使用索引,而不必扫描整个术语词典。您可能会在这里看到最大的性能提升。许多人似乎发现 2 是性能和会议搜索需求之间的良好平衡点。

其他可用参数也可以提供帮助:

  • maxEdits - 2是默认值,最大值。将此值设置为1将匹配更少,因此工作更快。

  • maxExpansions - 此查询会查找与模糊参数匹配的术语,然后搜索这些术语。如果您正在搜索短期条款,尤其是这个匹配条款列表可能会很长。设置maxExpansions将阻止发生这些极长的匹配列表。默认值为50.

  • transpositions - 是否允许交换两个字符。默认为true。基本上,Levenshtein和Damerau-Levenshtein之间的区别。假是工作少,匹配少,所以表现更好。不知道差异是否会那么大。