2016-12-16 3 views
0

내 시나리오는 모든 응용 프로그램에서 일반적인 시나리오라고 생각합니다. 공통적으로 사용되는 도메인 인 제품 및 제품 주문 항목을 예로 사용합니다.RavenDb의 관련 문서 필드별로 검색 색인을 만드는 방법은 무엇입니까?

내가하려는 것은 주문에 itens 목록이 있고 각 상품에 관련된 productId가 있다는 점을 고려하여 제품 이름별로 검색 주문을하는 것입니다.

일부 검색을 수행하고 Raven 설명서를 읽었지만 내 문제의 답을 찾을 수 없습니다.

public class Product 
    { 
     public string Id { get; set; } 
     public string ProductName { get; set; } 
     public decimal Price { get; set; } 
    } 

    public class Order 
    { 
     public string Id { get; set; } 
     public string OrderNumber { get; set; } 
     public decimal Total { get; set; } 
     public string Customer { get; set; } 
     public Item[] Items { get; set; } 
    } 

    public class Item 
    { 
     public string ProductId { get; set; } 
     public decimal Price { get; set; } 
     public int Quantity { get; set; } 
    } 


    public class Order_ByProductName : AbstractMultiMapIndexCreationTask<Order_ByProductName.Result> 
    { 
     public class Result 
     { 
      public string ProductId { get; set; } 
      public string ProductName { get; set; } 
      public string[] OrdersIds { get; set; } 
      public string[] OrdersNumbers { get; set; } 
     } 

     public Order_ByProductName() 
     { 
      AddMap<Product>(products => from product in products 
             select new 
             { 
              ProductId = product.Id, 
              ProductName = product.ProductName, 
              OrderId = default(string), 
              OrderNumber = default(string) 
             }); 

      AddMap<Order>(orders => from order in orders 
            group order by order.Items.Select(c => c.ProductId) 
            into g 
            select new 
            { 
             ProductId = g.Key, 
             ProductName = default(string), 
             OrdersIds = g.Select(c => c.Id), 
             OrdersNumbers = g.Select(c => c.OrderNumber) 
            }); 

      Reduce = results => from result in results 
           group result by result.ProductId 
           into g 
           select new 
           { 
            ProductId = g.Key, 
            ProductName = g.Select(r => r.ProductName).Where(t => t != null).First(), 
            OrdersIds = g.Where(r => r.OrdersIds != null).SelectMany(r => r.OrdersIds), 
            OrdersNumbers = g.Where(r => r.OrdersNumbers != null).SelectMany(r => r.OrdersNumbers) 
           }; 

      Sort("ProductName", SortOptions.String); 
      Index(x => x.ProductName, FieldIndexing.Analyzed); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var documentStore = new DocumentStore 
      { 
       Url = "http://localhost:8080", 
       DefaultDatabase = "MyDatabase" 
      }; 

      documentStore.Initialize(); 
      new Order_ByProductName().Execute(documentStore); 

      using (var session = documentStore.OpenSession()) 
      { 
       var product1 = new Product() { Price = 100, ProductName = "Phone" }; 
       var product2 = new Product() { Price = 1000, ProductName = "Laptop" }; 
       var product3 = new Product() { Price = 200, ProductName = "Windows Phone" }; 

       session.Store(product1); 
       session.Store(product2); 
       session.Store(product3); 
       session.SaveChanges(); 
      } 

      using (var session = documentStore.OpenSession()) 
      { 
       var products = session.Query<Product>().ToList(); 

       var order1 = new Order(); 
       order1.Customer = "Jhon Doe"; 
       order1.OrderNumber = "001"; 
       order1.Items = new Item[] { 
        new Item { ProductId = products[0].Id, Price = products[0].Price, Quantity = 1 }, 
        new Item { ProductId = products[1].Id, Price = products[1].Price, Quantity = 1 } 
       }; 
       order1.Total = order1.Items.Sum(c => (c.Quantity * c.Price)); 

       var order2 = new Order(); 
       order2.Customer = "Joan Doe"; 
       order2.OrderNumber = "002"; 
       order2.Items = new Item[] { 
        new Item { ProductId = products[2].Id, Price = products[2].Price, Quantity = 1 } 
       }; 
       order2.Total = order2.Items.Sum(c => (c.Quantity * c.Price)); 

       session.Store(order1); 
       session.Store(order2); 
       session.SaveChanges(); 
      } 

      using (var session = documentStore.OpenSession()) 
      { 
       var results = session 
        .Query<Order_ByProductName.Result, Order_ByProductName>() 
        .Where(x => x.ProductName == "Phone") 
        .ToList(); 

       foreach (var item in results) 
       { 
        Console.WriteLine($"{item.ProductName}\t{string.Join(", ", item.OrdersNumbers)}"); 
       } 

       Console.ReadKey(); 
      } 
     } 
    } 

내가 여기 How to index related documents in reverse direction in Ravendb 관련 문제를 발견하지만,이 시나리오는 약간 다릅니다 :

아래 코드를 고려하시기 바랍니다. 위의 코드는 인덱스 작성에 주석을 달지만 달리 예외가 있으면 실행됩니다. "쿼리를 이해할 수 없습니다 : 변수 이니셜 라이저는 선택 쿼리 식이어야합니다".

나는 SQL 아래에 있지만 RavenDb처럼 뭔가를해야만이 필요합니다

select pro.ProductName, ord.OrderNumber from orders ord 
inner join items itm on itm.OrderId = ord.Id 
inner join products pro on pro.Id = itm.ProductId 
where pro.ProductName like '%Phone%'; 

방법 제품 이름으로 검색을 만들고 RavenDb의 목록 또는 주문을 반환? Im 사용 버전 3.5 (.1)

"관련 엔터티 별 엔터티"검색과 같은 주된 문제를 고려하십시오.

미리 감사드립니다.

답변

2

제품 이름을 주문 항목에 직접 저장하는 것이 좋습니다. 그러면 두 가지 이점이 있습니다. 주문 항목은 나중에 제품을 변경하면 영향을받지 않으며 색인 생성은 더 저렴 해집니다.

public class Product 
{ 
    public string Id { get; set; } 
    public string ProductName { get; set; } 
    public decimal Price { get; set; } 
} 

public class Order 
{ 
    public string Id { get; set; } 
    public string OrderNumber { get; set; } 
    public decimal Total { get; set; } 
    public string Customer { get; set; } 
    public Item[] Items { get; set; } 
} 

public class Item 
{ 
    public string ProductId { get; set; } 
    public string ProductName { get; set; } 
    public decimal Price { get; set; } 
    public int Quantity { get; set; } 
} 

public class OrderView 
{ 
    public string OrderId { get; set; } 
    public string OrderNumber { get; set; } 
    public string[] ProductIds { get; set; } 
    public string[] ProductNames { get; set; } 
} 

public class Order_ByItemName : AbstractIndexCreationTask<Order, OrderView> 
{ 
    public Order_ByItemName() 
    { 
     Map = orders => from order in orders 
         select new 
         { 
          OrderId = order.Id, 
          OrderNumber = order.OrderNumber, 
          ProductIds = order.Items.Select(x => x.ProductId).ToArray(), 
          ProductNames = order.Items.Select(x => x.ProductName).ToArray(), 
         }; 

     Index(x => x.ProductNames, FieldIndexing.Analyzed); 
     StoreAllFields(FieldStorage.Yes); 
    } 
} 

public class Order_ByProductName : AbstractIndexCreationTask<Order, OrderView> 
{ 
    public Order_ByProductName() 
    { 
     Map = orders => from order in orders 
         let products = LoadDocument<Product>(order.Items.Select(x => x.ProductId)) 
         select new 
         { 
          OrderId = order.Id, 
          OrderNumber = order.OrderNumber, 
          ProductIds = products.Select(x => x.Id).ToArray(), 
          ProductNames = products.Select(x => x.ProductName).ToArray(), 
         }; 

     Index(x => x.ProductNames, FieldIndexing.Analyzed); 
     StoreAllFields(FieldStorage.Yes); 
    } 
} 

class Program 
{ 

    static void Main(string[] args) 
    { 
     var documentStore = new DocumentStore 
     { 
      Url = "http://localhost:8080", 
      DefaultDatabase = "MyDatabase" 
     }; 

     documentStore.Initialize(); 
     new Order_ByProductName().Execute(documentStore); 
     new Order_ByItemName().Execute(documentStore); 

     using (var session = documentStore.OpenSession()) 
     { 
      var product1 = new Product() { Id = "products/1", Price = 100, ProductName = "Phone" }; 
      var product2 = new Product() { Id = "products/2", Price = 1000, ProductName = "Laptop" }; 
      var product3 = new Product() { Id = "products/3", Price = 200, ProductName = "Windows Phone" }; 

      session.Store(product1); 
      session.Store(product2); 
      session.Store(product3); 
      session.SaveChanges(); 
     } 

     using (var session = documentStore.OpenSession()) 
     { 
      var products = session.Query<Product>().ToList(); 

      var order1 = new Order(); 
      order1.Id = "orders/1"; 
      order1.Customer = "Jhon Doe"; 
      order1.OrderNumber = "001"; 
      order1.Items = new Item[] { 
       new Item { ProductId = products[0].Id, ProductName = products[0].ProductName, Price = products[0].Price, Quantity = 1 }, 
       new Item { ProductId = products[1].Id, ProductName = products[1].ProductName, Price = products[1].Price, Quantity = 1 } 
      }; 
      order1.Total = order1.Items.Sum(c => (c.Quantity * c.Price)); 

      var order2 = new Order(); 
      order1.Id = "orders/1"; 
      order2.Customer = "Joan Doe"; 
      order2.OrderNumber = "002"; 
      order2.Items = new Item[] { 
       new Item { ProductId = products[2].Id, ProductName = products[2].ProductName, Price = products[2].Price, Quantity = 1 } 
      }; 
      order2.Total = order2.Items.Sum(c => (c.Quantity * c.Price)); 

      session.Store(order1); 
      session.Store(order2); 
      session.SaveChanges(); 
     } 
     Thread.Sleep(5000); // wait for indexing 

     using (var session = documentStore.OpenSession()) 
     { 
      var itemResults = session 
       .Query<OrderView, Order_ByItemName>() 
       .Search(x => x.ProductNames, "Phone") 
       .ProjectFromIndexFieldsInto<OrderView>() 
       .ToList(); 

      var results = session 
       .Query<OrderView, Order_ByProductName>() 
       .Search(x => x.ProductNames, "Phone") 
       .ProjectFromIndexFieldsInto<OrderView>() 
       .ToList(); 


      Console.WriteLine("Order_ByItemName"); 
      foreach (var order in itemResults) 
      { 
       Console.WriteLine($"OrderNumber: {order.OrderNumber}"); 
       for (int i = 0; i < order.ProductIds.Length; i++) 
       { 
        Console.WriteLine($"Item: {order.ProductIds[i]} - {order.ProductNames[i]}"); 
       } 
      } 

      Console.WriteLine("Order_ByProductName"); 
      foreach (var order in results) 
      { 
       Console.WriteLine($"OrderNumber: {order.OrderNumber}"); 
       for (int i = 0; i < order.ProductIds.Length; i++) 
       { 
        Console.WriteLine($"Item: {order.ProductIds[i]} - {order.ProductNames[i]}"); 
       } 
      } 

      Console.ReadKey(); 
     } 
    } 
} 
:

다음 코드는 두 가지 접근 방식을 보여줍니다

관련 문제