2012-04-20 78 views

回答

5

最後..

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

感謝您的代碼,作品如微風!當Doc有一個標題字段時,最好的方法是什麼?我想根據這個標題包含特定字符串的事實來過濾這些方面? – 2012-10-16 13:32:43

1

我處理這個使用純的Lucene的速度的緣故樹搜索的一部分。 2種方法是父子關聯方法和路徑枚舉/'杜威小數'方法。

親子是我們都學會了如何在算法類中實現鏈表。它很容易更新,但查詢需要訪問每個節點(例如,您不能直接從父母到其曾孫)。鑑於你需要訪問一個節點的所有祖先以獲得所有的屬性(因爲這個想法是分享屬性),所以必須訪問所有的祖先可能是一個有爭議的問題。

How to store tree data in a Lucene/Solr/Elasticsearch index or a NoSQL db?涵蓋路徑枚舉/'杜威小數'方法。

任何一種方法都可以處理任意複雜的層次結構,只要它是真正的層次結構(即有向無環圖(D.A.G.))。

+1

首先,感謝您的時間。但是,我需要澄清一件事......我的數據 - 存儲在Esent中 - 不是分層的;我的數據的不同方面是分層的。在Lucene語言中,我認爲它們被稱爲_terms_。所以這些術語本身是分層的。請參閱我在第36頁上方鏈接的論文,並查看右上角的圖表。使用你的方法,我會在Lucene中設計一個索引來查詢分層數據,但我正在尋找乾淨而簡單的資源來將這個概念應用於Lucene的術語:分層分類。 – maxbeaudoin 2012-04-20 20:44:08

1

我固定它了。

我創建指標如下:

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); 
    } 
} 

我查詢它想:

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");