11

我正在寻找一种编码 lucene 模糊查询的方法,该查询搜索与确切短语相关的所有文档。如果我搜索“mosa employee Appreciata”,一个包含“大多数员工欣赏”的文档将作为结果返回。

我尝试使用:

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

不幸的是,它凭经验是行不通的。FuzzyQuery 采用编辑器距离,理论上,“mosa employee apreciata”应该与“most employees 感谢”相匹配,只要给出适当的距离。似乎有点奇怪。

有什么线索吗?谢谢你。

4

4 回答 4

16

这里有两个可能的问题。首先:我猜测“内容”字段正在被分析,因此“大多数员工欣赏”不是一个术语,而是三个术语。在这种情况下,将其定义为单个术语是不合适的。

但是,即使列出的内容是单个术语,我们遇到的第二个可能的问题是术语之间的距离太大而无法匹配。mosa employee appreicata和之间的 Damerau-Levenshtein 距离most employees appreciate是 4(顺便说一下,我平均第一次拼写“Damerau-Levenshtein”与正确拼写之间的近似距离)。从 4.0 开始,Fuzzy Query 处理的编辑距离不超过 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 的编辑距离,因此这应该更有效。

于 2013-08-07T19:19:38.510 回答
1

ComplexPhraseQueryParser处理短语词的模糊搜索 - 即,指定应该模糊搜索的词和不应该模糊搜索的词。工作如下

Query query = new ComplexPhraseQueryParser("content", analyzer)
                    .parse("some test~ query~ blah blah");

似乎工作得很好。但是,不确定性能,但似乎在小型数据集上运行良好。

于 2019-04-02T14:53:44.780 回答
0

我有一些(非常小)以下内容:

String[] searchTerms = searchString.split(" ");
FuzzyLikeThisQuery fltw = new FuzzyLikeThisQuery(searchTerms.length, new StandardAnalyzer());
Arrays.stream(searchTerms)
    .forEach(term -> fltq.addTerms(term, FIELD, SIMILARITY_IN_EDITS, PREFIX_LENGTH); 

此查询将距离太远的字符串与索引匹配。不匹配的字符串是每个术语与索引内容中使用的术语相距超过 2 次编辑的字符串。

请自担风险使用。

于 2019-03-26T13:53:06.230 回答
-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();
于 2013-09-25T10:43:18.643 回答