2011-04-10 15 views
8

Busco una manera de encontrar los términos que coincidían en el documento mediante waldcard búsqueda en Lucene. Usé el explicador para tratar de encontrar los términos, pero esto falló. Una parte del código relevante está debajo.Obtención de términos coincidentes en un documento en la búsqueda utilizando una búsqueda comodín

ScoreDoc[] myHits = myTopDocs.scoreDocs; 
int hitsCount = myHits.Length; 
for (int myCounter = 0; myCounter < hitsCount; myCounter++) 
{ 
    Document doc = searcher.Doc(myHits[myCounter].doc); 
    Explanation explanation = searcher.Explain(myQuery, myCounter); 
    string myExplanation = explanation.ToString(); 
    ... 

Cuando hago una búsqueda en decir micro *, los documentos se encuentran y entrar en la serie, pero myExplanation contiene no coincidencia y ninguna otra información.

¿Cómo consigo el término que se encontró en este documento?

Cualquier ayuda sería muy apreciada.

Saludos

Respuesta

8
class TVM : TermVectorMapper 
    { 
     public List<string> FoundTerms = new List<string>(); 
     HashSet<string> _termTexts = new HashSet<string>(); 

     public TVM(Query q, IndexReader r) : base() 
     { 
      List<Term> allTerms = new List<Term>(); 
      q.Rewrite(r).ExtractTerms(allTerms); 
      foreach (Term t in allTerms) _termTexts.Add(t.Text()); 
     } 

     public override void SetExpectations(string field, int numTerms, bool storeOffsets, bool storePositions) 
     { 
     } 

     public override void Map(string term, int frequency, TermVectorOffsetInfo[] offsets, int[] positions) 
     { 
      if (_termTexts.Contains(term)) FoundTerms.Add(term); 
     } 
    } 

    void TermVectorMapperTest() 
    { 
     RAMDirectory dir = new RAMDirectory(); 
     IndexWriter writer = new IndexWriter(dir, new Lucene.Net.Analysis.Standard.StandardAnalyzer(), true); 
     Document d = null; 

     d = new Document(); 
     d.Add(new Field("text", "microscope aaa", Field.Store.YES, Field.Index.ANALYZED,Field.TermVector.WITH_POSITIONS_OFFSETS)); 
     writer.AddDocument(d); 

     d = new Document(); 
     d.Add(new Field("text", "microsoft bbb", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); 
     writer.AddDocument(d); 

     writer.Close(); 

     IndexReader reader = IndexReader.Open(dir); 
     IndexSearcher searcher = new IndexSearcher(reader); 

     QueryParser queryParser = new QueryParser("text", new Lucene.Net.Analysis.Standard.StandardAnalyzer()); 
     queryParser.SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE); 
     Query query = queryParser.Parse("micro*"); 

     TopDocs results = searcher.Search(query, 5); 
     System.Diagnostics.Debug.Assert(results.TotalHits == 2); 

     TVM tvm = new TVM(query, reader); 
     for (int i = 0; i < results.ScoreDocs.Length; i++) 
     { 
      Console.Write("DOCID:" + results.ScoreDocs[i].Doc + " > "); 
      reader.GetTermFreqVector(results.ScoreDocs[i].Doc, "text", tvm); 
      foreach (string term in tvm.FoundTerms) Console.Write(term + " "); 
      tvm.FoundTerms.Clear(); 
      Console.WriteLine(); 
     } 
    } 
+0

Tuve que modificar la clase TVM para usar HashTable para C#. Gracias funcionó como yo quería. – Puneet

+0

No tiene que modificarlo con Lucene.Net 2.9.4g en https://svn.apache.org/repos/asf/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src –

4

Una forma es utilizar el resaltador; otra forma sería la de imitar lo que hace el marcador reescribiendo su consulta llamando a myQuery.rewrite() con una re-escritura apropiada; esto es probablemente más cercano en espíritu a lo que estabas intentando. Esto volverá a escribir la consulta a un BooleanQuery que contiene todos los términos que encajen; puedes sacar las palabras de ellos con bastante facilidad. ¿Es eso suficiente para ponerte en marcha?

Ésta es la idea que tenía en mente; perdón por la confusión re: reescribir las consultas; no es realmente relevante aquí.

TokenStream tokens = TokenSources.getAnyTokenStream(IndexReader reader, int docId, String field, Analyzer analyzer); 
CharTermAttribute termAtt = tokens.addAttribute(CharTermAttribute.class); 
while (tokens.incrementToken()) { 
    // do something with termAtt, which holds the matched term 
} 
+0

En realidad lo que busco es ser capaz de obtener sólo aquellos términos que se encuentran en el documento. De modo que si un documento contiene microscopio y otro contiene microsoft, entonces, cuando esté en el primer documento, debería obtener solo el microscopio y cuando esté en el segundo documento, debería obtener solo microsoft como el término coincidente. Su sugerencia me daría todos los términos que se correspondería con micro * en el campo de índice. Espero poder explicar lo que estoy buscando. – Puneet

+0

Edité la respuesta - con suerte más cerca de lo que necesita –

Cuestiones relacionadas