我想出解决programmaticlly创建查询来搜索短语与使用此代码通配符:Lucene的短语查询与通配符
public static Query createPhraseQuery(String[] phraseWords, String field) {
SpanQuery[] queryParts = new SpanQuery[phraseWords.length];
for (int i = 0; i < phraseWords.length; i++) {
WildcardQuery wildQuery = new WildcardQuery(new Term(field, phraseWords[i]));
queryParts[i] = new SpanMultiTermQueryWrapper<WildcardQuery>(wildQuery);
}
return new SpanNearQuery(queryParts, //words
0, //max distance
true //exact order
);
}
实施例的创建和调用toString()方法将输出:
String[] phraseWords = new String[]{"foo*", "b*r"};
Query phraseQuery = createPhraseQuery(phraseWords, "text");
System.out.println(phraseQuery.toString());
输出:
spanNear([SpanMultiTermQueryWrapper(text:foo*), SpanMultiTermQueryWrapper(text:b*r)], 0, true)
这对于大多数情况下工作足够大,快。举例来说,如果我创造这样的查询与和它可以搜索,它会输出预期的效果,例如:
Sentence with foo bar.
Foolies beer drinkers.
...
而且不一样的东西:
Bar fooes.
Foo has bar.
我刚才提到的查询工作足够快在大多数情况下。目前我有一个大小为aprox的索引。 200GB,平均搜索时间在0.1到3秒之间。取决于许多因素,如:缓存,匹配单个单词的文档的子集大小,因为lucene将在创建的术语之间执行集合交集。让我想要查询短语“an * karenjin *”(我将分解为[“an *”,“karenjin *”]并且使用createPhraseQuery方法创建查询),我希望它匹配包含以下内容的句子:“ana karenjina”,“ani karenjinoj”,“an karenjine”,...(由于克罗地亚语语法不同的情况)。
这个查询是非常慢,我没有等待足够长的时间来获得结果(超过1小时),有时会导致GC开销限制超出异常。 由于“an *”本身匹配大量文档,因此会出现此行为。我知道我可以查询“an?karanjin *”,它可以在30-40秒内获得结果(更快但仍然很慢)。
这是我困惑的地方。 如果我只是查询“karenjin *”,它会在1秒内给出结果。因此,我尝试使用WildcardQuery和QueryWrapperFilter查询“an * karenjin *”并使用Filter“karenjin *”。而且它仍然是不能接受的缓慢(我在任何返回任何东西之前杀死了进程)。
文档说过滤器减少了查询的搜索空间。于是,我就用过滤:
Filter filter = new QueryWrapperFilter(new WildcardQuery(new Term("text", "karanjin*")));
和查询:
Query query = createPhraseQuery(new String[]{"an*", "karenjin*"}, "text");
比搜索(后几场热身查询):
Sort sort = new Sort(new SortField("insertTime", SortField.Type.STRING, true));
TopDocs docs = searcher.search(query, filter, 100, sort);
OK,什么是我的问题?
如何而来的是quering:
Query query = new WildcardQuery(new Term("text", "karanjin*"));
是快,但使用上述仍然缓慢过滤器?
谢谢你的建议,我会尽量限制条款的数量,看看它是如何执行。我期待它会快很多。但结果可能不完整。它是在时间和结果之间权衡的。 – 2014-09-30 00:30:23
我会试一试。根据Lucene的书中的内容,如果没有通配符,WildcardQuery将在内部识别并优化为PrefixQuery(如果以*结尾,或者甚至包含TermQuery)。 – 2014-09-30 00:37:19
我认为这是正确的,但我更希望逻辑生活在解析中,而我没有看到它。尽管可能是重写的一部分。 – femtoRgon 2014-09-30 01:27:16