He estado trabajando en un programa de búsqueda de documentos Lucene durante los últimos días y todo ha ido bien en general, hasta ahora. Intento usar la clase Lucene.Net.Highlight.Highlighter
para mostrar fragmentos relevantes para mis resultados de búsqueda, pero no funciona de manera consistente. La mayoría de los del momento en que llama a Highlighter.GetBestFragments()
hace exactamente lo que yo esperaría (muestra los fragmentos de texto relevantes con la cadena de consulta dada en ellos), pero a veces simplemente devuelve una cadena vacía.Lucene Hightlighter a veces inexplicablemente devuelve fragmentos en blanco
He comprobado tres veces mis entradas y puedo verificar que la cadena de consulta que estoy usando existe en el texto de entrada, pero el marcador simplemente devuelve arbitrariamente una cadena vacía a veces. El problema es reproducible; los documentos que tienen fragmentos en blanco devueltos continuarán teniendo fragmentos en blanco devueltos cuando se usa la misma consulta, mientras que los documentos que tienen fragmentos legítimos continúan teniendo fragmentos legítimos.
Sin embargo, el problema NO es específico del documento. Algunas consultas devuelven fragmentos válidos para un documento donde otras consultas devuelven una cadena vacía para el mismo documento. El problema tampoco parece estar relacionado con mi analizador; El problema aparece si utilizo un StandardAnalyzer
o un SnowballAnalyzer
.
Después de muchas horas de hurgar, no he podido encontrar ningún patrón en las consultas/documentos que fallan en comparación con los que funcionan. Tenga en cuenta que esto está sucediendo en documentos que fueron específicamente retirados del índice Lucene utilizando la misma consulta exacta. Eso significa que el Searcher
puede encontrar la cadena de consulta relevante en el documento de destino, pero el Highlighter
no lo está.
¿Esto es un error en Lucene? Si es así, ¿cómo puedo solucionarlo?
Mi código:
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;
}
}
(Nota:.. DVDoc
es esencialmente sólo una estructura que almacena información sobre los documentos que fueron encontrados El método MapLuceneDocumentToData
convierte una Lucene Document
en mi clase personalizada DVDoc
, hay magia allí)
y puesto que cada uno tiene gusto entradas y salidas ejemplo:
estoy usando Lucene.NET Versión 2.9.4g.
¿Ha intentado modificar el valor 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! Esto resolvió el problema de inmediato. No sé por qué nunca noté esa función en la documentación, debo haberla salteado. En cualquier caso, escriba su comentario como respuesta y lo aceptaré felizmente. – ean5533