Как получить совпадающие термины в нечетком результате поиска Lucene?

#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. Хотя это кажется немного хакерским (не ваша вина, просто кажется, что должен быть более чистый способ), это единственная рабочая реализация, которую я нашел. Спасибо!