短语上的Lucene模糊搜索(FuzzyQuery+;SpanQuery)

短语上的Lucene模糊搜索(FuzzyQuery+;SpanQuery),lucene,fuzzy-search,Lucene,Fuzzy Search,我正在寻找一种编码lucene模糊查询的方法,该查询搜索所有与确切短语相关的文档。如果我搜索“mosa employee Approvita”,结果将返回一个包含“most employee Approvita”的文档 我尝试使用: FuzzyQeury = new FuzzyQuery(new Term("contents","mosa employee appreicata")) 不幸的是,这在经验上是行不通的。FuzzyQuery使用编辑距离,理论上,“mosa员工欣赏”应该与“大多数员

我正在寻找一种编码lucene模糊查询的方法,该查询搜索所有与确切短语相关的文档。如果我搜索“mosa employee Approvita”,结果将返回一个包含“most employee Approvita”的文档

我尝试使用:

FuzzyQeury = new FuzzyQuery(new Term("contents","mosa employee appreicata"))
不幸的是,这在经验上是行不通的。FuzzyQuery使用编辑距离,理论上,“mosa员工欣赏”应该与“大多数员工欣赏”匹配,只要给出适当的距离。这似乎有点奇怪


有什么线索吗?谢谢。

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

然而,即使列出的内容是一个术语,第二个可能的问题是术语之间的距离太远,无法匹配。
mosa员工评价数据
和大多数员工欣赏的
之间的Damerau Levenshtein距离为4(顺便说一句,这是我第一次拼写的平均距离
“Damerau Levenshtein”和正确的拼写)。从4.0开始,模糊查询处理的编辑距离不超过2,这是由于性能限制,并且假设较大的距离通常并不特别相关

如果您需要使用模糊术语执行短语查询,您应该查看或组合一组(尤其是
spanmultitermqueryrapper
span-arquery
)以满足您的需要

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,因此这应该更有效。

来自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();
我有一些(非常小的)百万美元,包括:

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次编辑的字符串


请自行承担使用风险。
complexprasequeryparser
处理短语词的模糊搜索,即指定应模糊搜索的词和不应模糊搜索的词。工作如下

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

看起来效果不错。但是,不确定性能,但在小数据集上似乎效果很好。

需要更多详细信息:您是如何为内容字段编制索引的?你用的是什么分析仪?您是否尝试过更近距离的搜索(从准确的短语开始,然后更改单个字符…)?您在查询参数中提供了多少自由度?你到底得到了什么?你用过什么版本的lucene?我可以;似乎找不到适用于4.6的FuzzyTerminum api。在4.6中,只有FuzzyTermsEnum具有不同的构造函数,这实际上并没有达到您的目的。可能是针对您的简单示例,但不适用于包含更多文本的更复杂文档。因为FuzzyTermEnum没有从索引中的较大文档中给出正确的术语……我能用Lucene查询语言实现同样的功能吗?@isah-你是说用标准的QueryParser?不,你不能。可以…是的,我在问过你之后就用ComplexQueryParser完成了,谢谢。@femtoRgon你能举例说明一下如何用Complex短语解析器实现同样的功能吗?@pelican\u george-只需传递一个查询,如:
“\”mosa~ employee~ AppreCita~ \”