2010-12-21 8 views
6

Tengo un problema al ordenar mi índice lucene.net en .NET. Intenté casi todas las soluciones en stackoverflow y busqué respuestas en google. Estoy usando Lucene.NET 2.9.2 y ASP.NET 2.0. Quiero ordenar por cadena como en sql puede escribir 'ordenar por Título desc [asc]'Lucene.net 2.9.2 ordenación (la ordenación no funciona)

Le mostraré mi código y espero que alguien me pueda ayudar.

//Here I create Index with some fields 
    doc.Add(new Field("prod_id",row["prod_id"].ToString(),Field.Store.YES,Field.Index.ANALYZED)); 
      doc.Add(new Field("prod_title", row["prod_title"].ToString(), Field.Store.YES, Field.Index.ANALYZED)); 
      doc.Add(new Field("prod_desc", row["prod_desc"].ToString(), Field.Store.YES, Field.Index.ANALYZED)); 
      doc.Add(new Field("prod_author", row["prod_author"].ToString(), Field.Store.YES, Field.Index.ANALYZED)); 
      doc.Add(new Field("prod_publisher", row["prod_publisher"].ToString(), Field.Store.YES, Field.Index.ANALYZED)); 
      doc.Add(new Field("prod_price", row["prod_price"].ToString(), Field.Store.YES, Field.Index.ANALYZED)); 

//Then next I try to do search with sort option: 

//method for return approciate Sort object 
private static Sort SetSortForLucene(string _sort) 
    { 
     Sort sort; 
     switch (_sort) 
     { 
      case "UnitPriceGorss": 
       sort = new Sort(new SortField("prod_price",SortField.DOUBLE,false); 
       break; 

      case "UnitPriceGorssDESC": 
       sort = new Sort(new SortField("prod_price",SortField.DOUBLE,true); 
       break; 

      case "Title": 
       //not working 
       sort = new Sort(new SortField("prod_title", SortField.STRING, true)); 
       break; 

      case "TitleDESC": 
       //not working 
       sort = new Sort(new SortField("prod_title", SortField.STRING, false)); 
       break; 
      case "": 
       sort = new Sort(new SortField("prod_title", SortField.STRING, false)); 
       break; 
      default: 
       sort = new Sort(new SortField("prod_title", SortField.STRING, false)); 
       break; 
     } 
     return sort; 
    } 
//Inside my query of lucene method: 
StandardAnalyzer analizer = new StandardAnalyzer(Version.LUCENE_29); 
IndexReader reader =IndexReader.Open(IndexPath); 
Searcher searcher = new IndexSearcher(reader); 
//Here call for Sort object 
Sort sort = SetSortForLucene(_sort); 
TopFieldDocCollector collector = new TopFieldDocCollector(reader, sort, pageSize); 
//Find which document field need to me asked in QueryParser object 
string _luceneField = ""; 

     if (luceneField.Contains("_")) 
      _luceneField = luceneField; 
     else 
     switch (luceneField) 
     { 
      case "Title": _luceneField = "prod_title"; break; 
      case "Description": _luceneField = "prod_desc"; break; 
      case "Author": _luceneField = "prod_author"; break; 
      case "Publisher": _luceneField = "prod_publisher"; break; 
      default: _luceneField = "prod_title"; break; 
     } 
     QueryParser parser = new QueryParser(_luceneField, analizer); 
     Query query = parser.Parse(luceneQuery); 
     ScoreDoc[] hits; 
     searcher.Search(query,collector); 
//Obtaining top records from search but without any sort. 
     hits = collector.TopDocs().scoreDocs; 

     foreach (ScoreDoc hit in hits) 
     { 
      Document doc = searcher.Doc(hit.doc); 
      string a = doc.Get("prod_id"); 
      int id = 0; 
      if (hit.score > score) 
      { 
       if (int.TryParse(doc.Get("prod_id"), out id)) 
           tmpId.Add(id); 
      } 
     } 
//I also define stop words for full text searching and i think this is 
//real cause of problem with sorting. 
System.String[] stopWords = new System.String[]{"a","że","w","przy","o","bo","co","z","za","ze","ta","i","no","do"}; 

He utilizado este link in stackoverflow. y this pretty one link a resolver mi problema, pero falla clasificación y no sé lo que es malo en mi código.

Después de unos días finalmente encontré una solución. El campo que quiero ordenar no se tokenizará cuando represente el valor de la cadena.

Por ejemplo cuando quiero clasificar los productos por título (ascendente/descendente) se debe poner algo como esto:

doc.Add(new Field(Product.PROD_TITLE_SORT, row["prod_title"].ToString().Replace(" ", "_") + "_" + row[Product.PROD_ID].ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED)); 

Lo que no entiendo es por qué hecho de este campo no está almacenando y no analizyng y así lucene.net puede ordenar por este campo adicional. ¡Este campo de clasificación incluso no está en el índice! Lo verifiqué con el navegador de índice lukeall-1.0.1.jar.

En segundo lugar es necesario crear un método de ordenación adecuada:

private static Sort SetSortForLucene(string _sort) 
     { 
      Sort sort; 
      _sort = !string.IsNullOrEmpty(_sort) ? _sort : ""; 
      switch (_sort) 
      { 
       case "UnitPriceGorss": 
        sort = new Sort(new SortField(PROD_PRICE, SortField.DOUBLE, false)); 
        break; 

       case "UnitPriceGorssDESC": 
        sort = new Sort(new SortField(PROD_PRICE, SortField.DOUBLE, true)); 
        break; 

       case "Title": 
        //not it works perfectly. 
        sort = new Sort(new SortField(PROD_TITLE_SORT, SortField.STRING, true)); 
        break; 

       case "TitleDESC": 
        //not it works perfectly. 
        sort = new Sort(new SortField(PROD_TITLE_SORT, SortField.STRING, false)); 
        break; 
       case ""://Here is default sorting behavior. It get's result according to Lucene.NET search result score. 
        sort = new Sort(SortField.FIELD_SCORE); 
        break; 
       default: 
        sort = new Sort(SortField.FIELD_SCORE); 
        break; 
      } 
      return sort; 
     } 

Lo que me hace muy sospechoso es ese tipo trabaja con SortField.DOUBLE cuando el campo está indexada en el índice Lucene texto completo.

Espero que esta publicación ayude a cualquier persona que tenga un problema similar con la clasificación.

Respuesta

6

El campo no necesita ser almacenado a menos que regrese los datos en su consulta. Sin embargo, todavía se agrega al índice.

La razón por la que no analiza un campo que desea ordenar es que un analizador divide el campo en términos separados, lo que hace que la clasificación sea muy difícil ya que el índice del documento tendrá varias palabras, lo que obviamente no puede ser ordenados en contra del índice completo. Esto se aplica a todos los tipos de campo, ya sea que sean un solo término o no.

Creo que puede almacenar el campo, pero a menos que desee devolverlo en su consulta no es necesario.

4

una cosa importante que sospecho saber sobre la clasificación.

No funciona en datos tokenizados (analizados).

+0

Por lo tanto, agregue un campo no analizado para los datos que desea ordenar y utilícelo para ordenar, puede que tenga que duplicar el campo si también desea analizarlo. – Myster

Cuestiones relacionadas