5

Używam klasy rozświetlacza Lucene do zaznaczania fragmentów pasujących wyników wyszukiwania i działa dobrze. Chciałbym przełączyć się z przeszukiwania za pomocą narzędzia StandardAnalyzer na EnglishAnalyzer, który wykona wyrażenie warunków.Lucene Highlighter z analizatorem analizatora obrazu

Wyniki wyszukiwania są dobre, ale teraz wyróżnienie nie zawsze pasuje. Oto przykład tego, co patrzę:

document field text 1: Everyone likes goats. 

document field text 2: I have a goat that eats everything. 

Używanie EnglishAnalyzer i poszukiwania „koza”, oba dokumenty są dopasowane, ale wyróżnienia jest tylko w stanie znaleźć dopasowany fragment z dokumentu 2. Czy istnieje sposób, aby zakreślacz zwrócił dane dla obu dokumentów?

Rozumiem, że postacie są różne dla żetonów, ale te same żetony są nadal dostępne, więc wydaje się rozsądne, aby podświetlić tylko token, który jest obecny w tej lokalizacji.

Jeśli to pomaga, używa się Lucene 3.5.

Odpowiedz

7

Znalazłem rozwiązanie tego problemu. Zmieniłem klasę Highlighter na używanie FastVectorHighlighter. Wygląda na to, że dostanę też trochę ulepszeń szybkości (kosztem przechowywania danych wektorowych terminów). Dla dobra każdego, kto natknie się na to pytanie w późniejszym czasie, oto test jednostkowy pokazujący, jak to wszystko działa razem:

package com.sample.index; 

import org.apache.lucene.analysis.Analyzer; 
import org.apache.lucene.analysis.en.EnglishAnalyzer; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.index.IndexReader; 
import org.apache.lucene.index.IndexWriter; 
import org.apache.lucene.index.IndexWriterConfig; 
import org.apache.lucene.queryParser.ParseException; 
import org.apache.lucene.queryParser.QueryParser; 
import org.apache.lucene.search.IndexSearcher; 
import org.apache.lucene.search.Query; 
import org.apache.lucene.search.ScoreDoc; 
import org.apache.lucene.search.TopDocs; 
import org.apache.lucene.search.vectorhighlight.*; 
import org.apache.lucene.store.RAMDirectory; 
import org.apache.lucene.util.Version; 
import org.junit.Before; 
import org.junit.Test; 

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import static junit.framework.Assert.assertEquals; 

public class TestIndexStuff { 
    public static final String FIELD_NORMAL = "normal"; 
    public static final String[] PRE_TAGS = new String[]{"["}; 
    public static final String[] POST_TAGS = new String[]{"]"}; 
    private IndexSearcher searcher; 
    private Analyzer analyzer = new EnglishAnalyzer(Version.LUCENE_35); 

    @Before 
    public void init() throws IOException { 
     RAMDirectory idx = new RAMDirectory(); 
     IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer); 

     IndexWriter writer = new IndexWriter(idx, config); 
     addDocs(writer); 
     writer.close(); 

     searcher = new IndexSearcher(IndexReader.open(idx)); 
    } 

    private void addDocs(IndexWriter writer) throws IOException { 
     for (String text : new String[] { 
       "Pretty much everyone likes goats.", 
       "I have a goat that eats everything.", 
       "goats goats goats goats goats"}) { 
      Document doc = new Document(); 
      doc.add(new Field(FIELD_NORMAL, text, Field.Store.YES, 
        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); 
      writer.addDocument(doc); 
     } 
    } 

    private FastVectorHighlighter makeHighlighter() { 
     FragListBuilder fragListBuilder = new SimpleFragListBuilder(200); 
     FragmentsBuilder fragmentBuilder = new SimpleFragmentsBuilder(PRE_TAGS, POST_TAGS); 
     return new FastVectorHighlighter(true, true, fragListBuilder, fragmentBuilder); 
    } 

    @Test 
    public void highlight() throws ParseException, IOException { 
     Query query = new QueryParser(Version.LUCENE_35, FIELD_NORMAL, analyzer) 
        .parse("goat"); 
     FastVectorHighlighter highlighter = makeHighlighter(); 
     FieldQuery fieldQuery = highlighter.getFieldQuery(query); 

     TopDocs topDocs = searcher.search(query, 10); 
     List<String> fragments = new ArrayList<String>(); 
     for (ScoreDoc scoreDoc : topDocs.scoreDocs) { 
      fragments.add(highlighter.getBestFragment(fieldQuery, searcher.getIndexReader(), 
        scoreDoc.doc, FIELD_NORMAL, 10000)); 
     } 

     assertEquals(3, fragments.size()); 
     assertEquals("[goats] [goats] [goats] [goats] [goats]", fragments.get(0).trim()); 
     assertEquals("Pretty much everyone likes [goats].", fragments.get(1).trim()); 
     assertEquals("I have a [goat] that eats everything.", fragments.get(2).trim()); 
    } 
}