2012-05-23 27 views
6

Pracuję na Lucene programu wyszukującego dokument w ciągu ostatnich kilku dni, a wszystko zostało ogólnie dobrze, aż do teraz. Próbuję użyć klasy Lucene.Net.Highlight.Highlighter, aby wyświetlać odpowiednie fragmenty wyników wyszukiwania, ale nie działa to konsekwentnie. Większość czasu wywołania Highlighter.GetBestFragments() robi dokładnie to, czego oczekiwałbym (pokazuje odpowiednie fragmenty tekstu z danym łańcuchem zapytania w nich), ale czasami po prostu zwraca pusty ciąg.Lucene Hightlighter czasami niewytłumaczalny zwraca puste fragmenty

Mam potrójne sprawdzone moje wejścia i mogę sprawdzić, czy ciąg kwerendy używam występuje w tekście wejściowym, ale highlighter tylko arbitralnie zwraca pusty ciąg czasami. Problem jest powtarzalny; dokumenty, które mają zwrócone puste fragmenty, będą nadal miały puste fragmenty zwrócone podczas korzystania z tego samego zapytania, podczas gdy dokumenty, które zawierają uzasadnione fragmenty, nadal będą zawierać uzasadnione fragmenty.

Problem jednak NIE jest związany z dokumentem. Niektóre zapytania zwracają poprawne fragmenty dokumentu, gdzie inne zapytania zwracają pusty ciąg dla tego samego dokumentu. Problem również nie wydaje się być związany z moim analizatorem; pojawia się problem, czy używam StandardAnalyzer lub SnowballAnalyzer.

Po wielu godzinach wywiercenie Nie udało mi się znaleźć żadnego wzorca w zapytaniach/dokumenty, które nie w porównaniu z tymi, które działają. Należy pamiętać, że dzieje się tak w dokumentach, które zostały specjalnie wycofane z indeksu Lucene przy użyciu dokładnie tego samego zapytania. Oznacza to, że Searcher jest w stanie znaleźć odpowiedni ciąg zapytania w dokumencie docelowym, ale nie jest to Highlighter.

Czy to błąd w Lucene? Jeśli tak, jak mogę obejść ten problem?

Mój kod:

private static SimpleHTMLFormatter _formatter = new SimpleHTMLFormatter("<b>", "</b>"); 
private static SimpleFragmenter _fragmenter = new SimpleFragmenter(50); 
... 
{ 
    using (var searcher = new IndexSearcher(analyzerInfo.Directory, false)) 
    { 
     QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Text", analyzerInfo.Analyzer); 
     parser.SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE); 

     //build query 
     BooleanQuery booleanQuery = new BooleanQuery(); 
     booleanQuery.Add(new TermQuery(new Term("PageNum", "0")), BooleanClause.Occur.MUST); 
     booleanQuery.Add(parser.Parse(searchQuery), BooleanClause.Occur.MUST); 
     Query query = booleanQuery.Rewrite(searcher.GetIndexReader()); 

     //get results from query 
     ScoreDoc[] hits = searcher.Search(query, 50).ScoreDocs; 
     List<DVDoc> results = hits.Select(hit => MapLuceneDocumentToData(searcher.Doc(hit.Doc))).ToList(); 

     //add relevant fragments to search results (shows WHY a certain result was chosen) 
     QueryScorer scorer = new QueryScorer(query); 
     Highlighter highlighter = new Highlighter(_formatter, scorer); 
     highlighter.SetTextFragmenter(_fragmenter); 
     foreach (DVDoc result in results) 
     { 
      TokenStream stream = analyzerInfo.Analyzer.TokenStream("Text", new StringReader(result.Text)); 
      result.RelevantFragments = highlighter.GetBestFragments(stream, result.Text, 3, "..."); 
     } 

     //clean up 
     analyzerInfo.Analyzer.Close(); 
     searcher.Close(); 

     return results; 
    } 
} 

(Uwaga:.. DVDoc jest zasadniczo tylko struktura, która przechowuje informacje o dokumentach, które zostały znalezione Sposób MapLuceneDocumentToData zamienia Lucene Document w moim zwyczaju DVDoc klasy, nie magia istnieje)

A ponieważ każdy lubi przykładowych wejść i wyjść:

Używam Lucene.NET Wersja 2.9.4g.

+2

próbowałeś modyfikując wartość MaxDocCharsToAnalyze? http://lucene.apache.org/core/old_versioned_docs/versions/2_9_2/api/contrib-highlighter/org/apache/lucene/search/highlight/Highlighter.html#setMaxDocCharsToAnalyze(int) –

+0

@JfBeaulac Brilliant! To natychmiast rozwiązało problem. Nie wiem, dlaczego nigdy nie zauważyłem tej funkcji w dokumentacji, musiałem ją pominąć. W każdym razie, napisz swój komentarz jako odpowiedź, a ja z przyjemnością go zaakceptuję. – ean5533

Odpowiedz

9

Domyślnie Marker przetwarza tylko pierwsze 51200 znaków dokumentu.

Aby zwiększyć ten limit, należy ustawić właściwość MaxDocCharsToAnalyze.

http://lucene.apache.org/core/old_versioned_docs/versions/2_9_2/api/contrib-highlighter/org/apache/lucene/search/highlight/Highlighter.html#setMaxDocCharsToAnalyze(int)

+1

Po prostu z ciekawości, czy ktoś może mi powiedzieć, jakie jest najlepsze podejście, jeśli mam do analizy bardzo duże dokumenty? Zgaduję, że właściwość MaxDocCharsToAnalyze można ustawić na Int32.MaxValue, która jest obecnie 2147483647. Co się stanie, jeśli będę musiał przeanalizować tekst, który jest czymś więcej? – Vineet

Powiązane problemy