2012-04-20 12 views
6

Sto considerando RavenDb per implementare uno scenario di "ricerca a faccette avanzate".
Devo affrontare una complessa tassonomia gerarchica e le faccette condivise tra i diversi rami dell'albero, supportando la ricerca di testo completo e tutte le altre funzionalità di base.Tassonomia gerarchica nella ricerca sfaccettata utilizzando RavenDb/Lucene?

C'è qualche risorsa là fuori che documenta come farlo usando l'API RavenDb?

Insanely complesso documento sul tema: Beyond Basic Faceted Search
modo di Solr: HierarchicalFaceting

risposta

5

Infine ..

using System.Collections.Generic; 
using System.Linq; 
using NUnit.Framework; 
using Raven.Abstractions.Data; 
using Raven.Client; 
using Raven.Client.Document; 
using Raven.Client.Indexes; 
using Raven.Client.Linq; 

namespace Prototype.Search.Tests 
{ 
    [TestFixture] 
    public class HierarchicalFaceting 
    { 
     // 
     // Document definition 
     // 
     public class Doc 
     { 
      public Doc() 
      { 
       Categories = new List<string>(); 
      } 

      public int Id { get; set; } 
      public List<string> Categories { get; set; } 
     } 

     // 
     // Data sample 
     // 
     public IEnumerable<Doc> GetDocs() 
     { 
      yield return new Doc { Id = 1, Categories = new List<string> { "0/NonFic", "1/NonFic/Law"} }; 
      yield return new Doc { Id = 2, Categories = new List<string> { "0/NonFic", "1/NonFic/Sci" } }; 
      yield return new Doc { Id = 3, Categories = new List<string> { "0/NonFic", "1/NonFic/Hist", "1/NonFic/Sci", "2/NonFic/Sci/Phys" } }; 
     } 

     // 
     // The index 
     // 
     public class DocByCategory : AbstractIndexCreationTask<Doc, DocByCategory.ReduceResult> 
     { 
      public class ReduceResult 
      { 
       public string Category { get; set; } 
      } 

      public DocByCategory() 
      { 
       Map = docs => 
         from d in docs 
         from c in d.Categories 
         select new 
           { 
            Category = c 
           }; 
      } 
     } 

     // 
     // FacetSetup 
     // 
     public FacetSetup GetDocFacetSetup() 
     { 
      return new FacetSetup 
         { 
          Id = "facets/Doc", 
          Facets = new List<Facet> 
             { 
              new Facet 
               { 
                Name = "Category" 
               } 
             } 
         }; 
     } 

     [SetUp] 
     public void SetupDb() 
     { 
      IDocumentStore store = new DocumentStore() 
      { 
       Url = "http://localhost:8080" 
      }; 
      store.Initialize(); 
      IndexCreation.CreateIndexes(typeof(HierarchicalFaceting).Assembly, store); 

      var session = store.OpenSession(); 
      session.Store(GetDocFacetSetup()); 
      session.SaveChanges(); 

      store.Dispose(); 
     } 

     [Test] 
     [Ignore] 
     public void DeleteAll() 
     { 
      IDocumentStore store = new DocumentStore() 
      { 
       Url = "http://localhost:8080" 
      }; 
      store.Initialize(); 

      store.DatabaseCommands.DeleteIndex("Raven/DocByCategory"); 
      store.DatabaseCommands.DeleteByIndex("Raven/DocumentsByEntityName", new IndexQuery()); 

      store.Dispose(); 
     } 

     [Test] 
     [Ignore] 
     public void StoreDocs() 
     { 
      IDocumentStore store = new DocumentStore() 
      { 
       Url = "http://localhost:8080" 
      }; 
      store.Initialize(); 

      var session = store.OpenSession(); 

      foreach (var doc in GetDocs()) 
      { 
       session.Store(doc); 
      } 

      session.SaveChanges(); 
      session.Dispose(); 
      store.Dispose(); 
     } 

     [Test] 
     public void QueryDocsByCategory() 
     { 
      IDocumentStore store = new DocumentStore() 
      { 
       Url = "http://localhost:8080" 
      }; 
      store.Initialize(); 

      var session = store.OpenSession(); 

      var q = session.Query<DocByCategory.ReduceResult, DocByCategory>() 
       .Where(d => d.Category == "1/NonFic/Sci") 
       .As<Doc>(); 

      var results = q.ToList(); 
      var facetResults = q.ToFacets("facets/Doc").ToList(); 

      session.Dispose(); 
      store.Dispose(); 
     } 

     [Test] 
     public void GetFacets() 
     { 
      IDocumentStore store = new DocumentStore() 
      { 
       Url = "http://localhost:8080" 
      }; 
      store.Initialize(); 

      var session = store.OpenSession(); 

      var q = session.Query<DocByCategory.ReduceResult, DocByCategory>() 
       .Where(d => d.Category.StartsWith("1/NonFic")) 
       .As<Doc>(); 

      var results = q.ToList(); 
      var facetResults = q.ToFacets("facets/Doc").ToList(); 

      session.Dispose(); 
      store.Dispose(); 
     } 
    } 
} 
+0

grazie per il codice, funziona come un gioco da ragazzi! Qual è l'approccio migliore quando Doc ha anche un campo titolo e voglio filtrare le faccette in base al fatto che questo titolo contiene una determinata stringa? –

1

vorrei gestire la parte dell'albero-ricerca di questo utilizzando puro Lucene per il bene di velocità. 2 approcci sono il metodo di collegamento genitore-figlio e il metodo di enumerazione del percorso/'Dewey Decimal'.

Genitore-figlio è il modo in cui tutti abbiamo imparato a implementare gli elenchi collegati nella classe dell'algoritmo. È facile da aggiornare, ma le query richiedono la visita di ciascun nodo (ad esempio, non è possibile ottenere direttamente da un genitore al proprio pronipote). Dato che è necessario visitare comunque tutti gli antenati di un nodo per ottenere tutti gli attributi (poiché l'idea è di condividere gli attributi), dover visitare tutti gli antenati potrebbe essere un punto controverso.

How to store tree data in a Lucene/Solr/Elasticsearch index or a NoSQL db? copre il metodo enumeration/Dewey Decimal.

Entrambi gli approcci possono gestire una gerarchia arbitrariamente complessa, purché sia ​​una vera gerarchia (cioè un grafico aciclico diretto (D.A.G.)).

+1

In primo luogo, grazie per il vostro tempo. Tuttavia, ho bisogno di chiarire una cosa ... i miei dati - memorizzati in Esent - non sono gerarchici; I diversi aspetti dei miei dati sono gerarchici. Nella lingua lucena, credo che siano definiti come "teri". Quindi i termini stessi sono gerarchici. Fare riferimento alla carta che ho collegato sopra la pagina 36 e guardare il grafico nell'angolo in alto a destra. Utilizzando il tuo approccio, progetterei un indice in Lucene per interrogare i dati gerarchici, ma sto cercando risorse semplici e pulite per applicare questo concetto ai termini di Lucene: una tassonomia gerarchica. – maxbeaudoin

1

ho riparato già.

creo l'indice come segue:

public class ProductByCategory : AbstractIndexCreationTask<Product, ProductByCategory.ReduceResult> 
{ 
    public class ReduceResult 
    { 
     public string Category { get; set; } 
     public string Title { get; set; } 
    } 

    public ProductByCategory() 
    { 
     Map = products => 
       from p in products 
       from c in p.Categories 
       select new 
       { 
        Category = c, 
        Title = p.Title 
       }; 
     Stores.Add(x => x.Title, FieldStorage.Yes); 
     Indexes.Add(x => x.Title, FieldIndexing.Analyzed); 
    } 
} 

E interrogo le cose come:

var q = session.Query<ProductByCategory.ReduceResult, ProductByCategory>().Search(x => x.Title, "Sony") 
.Where(r => r.Category.StartsWith("1/beeld en geluid")).As<Product>(); 

var facetResults = q.ToFacets("facets/ProductCategory"); 
Problemi correlati