2012-05-23 10 views
6

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.

+2

¿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) –

+0

@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

Respuesta

9

De forma predeterminada, el resaltador solo procesará los primeros 51200 caracteres de un documento.

Para aumentar este límite, configure la propiedad 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

Solo por curiosidad, ¿alguien me puede decir cuál sería el mejor enfoque si tengo documentos muy grandes para analizar? Supongo que la propiedad MaxDocCharsToAnalyze se puede establecer en Int32.MaxValue, que actualmente es 2147483647. ¿Qué sucede si necesito analizar el texto que es más que esto? – Vineet

Cuestiones relacionadas