#java #lucene #fuzzy-search
#java #lucene #нечеткий поиск
Вопрос:
как получить совпадающий нечеткий термин и его смещение при использовании Lucene Fuzzy Search?
IndexSearcher mem = ....(some standard code)
QueryParser parser = new QueryParser(Version.LUCENE_30, CONTENT_FIELD, analyzer);
TopDocs topDocs = mem.search(parser.parse("wuzzy~"), 1);
// the ~ triggers the fuzzy search as per "Lucene In Action"
Нечеткий поиск работает нормально. Если документ содержит термин «нечеткий» или «luzzy», он соответствует. Как мне узнать, какой термин соответствует и каковы их смещения?
Я убедился, что все CONTENT_FIELDs добавлены с помощью termVectorStored с позициями и смещениями.
Комментарии:
1. Вы ищете что-то в этом роде? lucene. apache.org/java/3_0_0/api/contrib-highlighter/index.html
2. Нет. Я не ищу текст highlight; Мне нужно выполнить дальнейшую обработку текста. Прежде чем выполнять дальнейшую обработку текста, мне нужно выяснить, какому термину соответствует «нечеткий» или «luzzy» и т.д., Поскольку это нечеткое совпадение.
Ответ №1:
Прямого способа сделать это не было, однако я пересмотрел предложение Джареда и смог заставить решение работать.
Я документирую это здесь на случай, если у кого-то еще возникнет такая же проблема.
Создайте класс, который реализует org.apache.lucene.search.highlight.Formatter
public class HitPositionCollector implements Formatter
{
// MatchOffset is a simple DTO
private List<MatchOffset> matchList;
public HitPositionCollector(
{
matchList = new ArrayList<MatchOffset>();
}
// this ie where the term start and end offset as well as the actual term is captured
@Override
public String highlightTerm(String originalText, TokenGroup tokenGroup)
{
if (tokenGroup.getTotalScore() <= 0)
{
}
else
{
MatchOffset mo= new MatchOffset(tokenGroup.getToken(0).toString(), tokenGroup.getStartOffset(),tokenGroup.getEndOffset());
getMatchList().add(mo);
}
return originalText;
}
/**
* @return the matchList
*/
public List<MatchOffset> getMatchList()
{
return matchList;
}
}
Основной код
public void testHitsWithHitPositionCollector() throws Exception
{
System.out.println(" .... testHitsWithHitPositionCollector");
String fuzzyStr = "bro*";
QueryParser parser = new QueryParser(Version.LUCENE_30, "f", analyzer);
Query fzyQry = parser.parse(fuzzyStr);
TopDocs hits = searcher.search(fzyQry, 10);
QueryScorer scorer = new QueryScorer(fzyQry, "f");
HitPositionCollector myFormatter= new HitPositionCollector();
//Highlighter(Formatter formatter, Scorer fragmentScorer)
Highlighter highlighter = new Highlighter(myFormatter,scorer);
highlighter.setTextFragmenter(
new SimpleSpanFragmenter(scorer)
);
Analyzer analyzer2 = new SimpleAnalyzer();
int loopIndex=0;
//for (ScoreDoc sd : hits.scoreDocs) {
Document doc = searcher.doc( hits.scoreDocs[0].doc);
String title = doc.get("f");
TokenStream stream = TokenSources.getAnyTokenStream(searcher.getIndexReader(),
hits.scoreDocs[0].doc,
"f",
doc,
analyzer2);
String fragment = highlighter.getBestFragment(stream, title);
System.out.println(fragment);
assertEquals("the quick brown fox jumps over the lazy dog", fragment);
MatchOffset mo= myFormatter.getMatchList().get(loopIndex );
assertTrue(mo.getEndPos()==15);
assertTrue(mo.getStartPos()==10);
assertTrue(mo.getToken().equals("brown"));
}
Комментарии:
1. Хотя это кажется немного хакерским (не ваша вина, просто кажется, что должен быть более чистый способ), это единственная рабочая реализация, которую я нашел. Спасибо!