2013-08-07 70 views
9

我正在寻找一种对lucene模糊查询进行编码的方法,它可以搜索与精确短语相关的所有文档。如果我搜索“莫萨员工欣赏”,那么包含“大多数员工欣赏”的文档将作为结果返回。Lucene在一个短语上进行模糊搜索(FuzzyQuery + SpanQuery)

我试着使用:

FuzzyQeury = new FuzzyQuery(new Term("contents","mosa employee appreicata")) 

不幸的是,经验是行不通的。 FuzzyQuery应用编辑距离,理论上讲,“莫萨员工欣赏”应该与“大多数员工欣赏”相匹配,并给出适当的距离。这似乎有点奇怪。

任何线索?谢谢。

+0

需要额外的详细信息:您是如何为内容字段编制索引的?你在用什么分析仪?您是否尝试过更近距离的搜索(从确切的词组开始,然后更改单个字符,...)?你在查询参数中给了多少纬度?你究竟得到了什么? –

回答

1

femtoRgon的答案很棒!谢谢。

还有另一种方法可以解决这个问题。

//declare a mutilphrasequery 
MultiPhraseQuery childrenInOrder = new MultiPhraseQuery(); 

//user fuzzytermenum to enumerate your query string 
FuzzyTermEnum fuzzyEnumeratedTerms1 = new FuzzyTermEnum(reader, new Term(searchField,"mosa")); 
FuzzyTermEnum fuzzyEnumeratedTerms2 = new FuzzyTermEnum(reader, new Term(searchField,"employee")); 
FuzzyTermEnum fuzzyEnumeratedTerms3 = new FuzzyTermEnum(reader, new Term(searchField,"appreicata")); 

//this basically pull out the possbile terms from the index    
Term termHolder1 = fuzzyEnumeratedTerms1.term(); 
Term termHolder2 = fuzzyEnumeratedTerms2.term(); 
Term termHolder3 = fuzzyEnumeratedTerms3.term(); 

//put the possible terms into multiphrasequery 
if (termHolder1==null){ 
    childrenInOrder.add(new Term(searchField,"mosa")); 
}else{ 
    childrenInOrder.add(fuzzyEnumeratedTerms1.term()); 
} 

if (termHolder2==null){ 
    childrenInOrder.add(new Term(searchField,"employee")); 
}else{ 
    childrenInOrder.add(fuzzyEnumeratedTerms2.term()); 
} 

if (termHolder3==null){ 
    childrenInOrder.add(new Term(searchField,"appreicata")); 
}else{ 
    childrenInOrder.add(fuzzyEnumeratedTerms3.term()); 
} 


//close it - it is important to close it 
fuzzyEnumeratedTerms1.close(); 
fuzzyEnumeratedTerms2.close(); 
fuzzyEnumeratedTerms3.close(); 
+3

你使用了什么版本的lucene?我似乎无法找到4.6的FuzzyTermEnum api。在4.6只有FuzzyTermsEnum与不同的构造函数 – nir

+0

恕我直言,这实际上并没有做你想要的。也许是你的简单例子,但不适用于更多文本更复杂的文档。由于FuzzyTermEnum没有为索引中的较大文档提供正确的条款...... –

11

这里有两个可能的问题。首先:我在猜测“内容”字段正在被分析,以至于“大多数员工都会说”不是一个术语,而是三个术语。在这种情况下,定义为单个术语并不合适。

但是,即使列出的内容是单个术语,但我们可能遇到的第二个问题是术语之间的距离太大以致无法匹配。 mosa employee appreicatamost employees appreciate之间的Damerau-Levenshtein距离是4(顺便说一下,我在拼写为 “Damerau-Levenshtein”的平均第一次投射和正确拼写之间的近似距离)。从4.0开始,模糊查询处理的编辑距离不超过2,这是由于性能限制,以及较大距离通常不是特别相关的假设。

如果您需要执行的模糊条款短语查询,你应该考虑要么MultiPhraseQuery,或结合了一套SpanQueries(尤其是SpanMultiTermQueryWrapperSpanNearQuery),以满足您的需求。

SpanQuery[] clauses = new SpanQuery[3]; 
clauses[0] = new SpanMultiTermQueryWrapper(new FuzzyQuery(new Term("contents", "mosa"))); 
clauses[1] = new SpanMultiTermQueryWrapper(new FuzzyQuery(new Term("contents", "employee"))); 
clauses[2] = new SpanMultiTermQueryWrapper(new FuzzyQuery(new Term("contents", "appreicata"))); 
SpanNearQuery query = new SpanNearQuery(clauses, 0, true) 

而且由于没有一个单独的术语的编辑距离大于2,这应该更有效。

+0

使用Lucene查询语言可以实现同样的功能吗? – isah

+0

@isah - 你的意思是标准的QueryParser? *你不能。 [ComplexPhrase解析器](https://lucene.apache.org/core/5_5_0/queryparser/org/apache/lucene/queryparser/complexPhrase/ComplexPhraseQueryParser.html)可以... – femtoRgon

+0

是的,我刚刚用ComplexQueryParser完成它问你,谢谢。 – isah