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.
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) –
@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