2017-02-09 38 views
0

我正在構建一個索引,但結果並不如預期。Ravendb地圖/縮小指數不起作用

我的意圖是找到我在MyClass的SomeEnumFlag中有多少客戶和供應商。 MyClass有Name和SomeEnumFlag,它是一種買入或賣出的文件。所以,我可以有這樣的文件:

{ Name: "Some company name", SomeEnumFlag: "Buy" }, 
{ Name: "Another company name", SomeEnumFlag: "Buy" }, 
{ Name: "Another company name", SomeEnumFlag: "Sell" }, 
{ Name: "Another company name", SomeEnumFlag: "Sell" } 

預期的結果是:

  • 客戶:2;因爲有兩個與「買」不同的公司;
  • 供應商:1; 「原因有一個不同的公司以‘賣出’

所以,一個公司可以在客戶端和/或基於SomeEnumFlag供應商,每一次我應該算。

考慮指數:

public class MyClass_TotalClientsSuppliers_Index : AbstractIndexCreationTask<MyClass, MyClass_TotalClientsSuppliers_Index.Result> 
{ 
    public class Result 
    { 
     public string Kind { get; set; } 
     public int Total { get; set; } 
    } 

    public MyClass_TotalClientsSuppliers_Index() 
    { 
     Map = myClass => from grouped in myClass.GroupBy(c => new { Name = c.Name, Flag = c.SomeEnumFlag.ToString() }) 
           select new 
           { 
            Kind = grouped.Key.Flag, 
            Total = 1 
           }; 

     Reduce = results => from result in results 
          group result by result.Kind into g 
          select new 
          { 
           Kind = g.Key, 
           Total = g.Sum(c => c.Total) 
          }; 
    } 
} 

和查詢:

var resultTotalClientSupplier = session 
         .Query<MyClass_TotalClientsSuppliers_Index.Result, MyClass_TotalClientsSuppliers_Index>() 
         .ToList(); 

var totalClients = resultTotalClientSupplier.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Buy.ToString())?.Total ?? 0; 
var totalSuppliers = resultTotalClientSupplier.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Sell.ToString())?.Total ?? 0; 

totalClients = 2

totalSuppliers = 2,其是錯誤的。

但是,如果我寫這樣的代碼:

var myClasses = session.Query<MyClass>().ToList(); 

var map = from grouped in myClasses.GroupBy(c => new { Name = c.Name, Flag = c.SomeEnumFlag.ToString() }) 
           select new 
           { 
            Kind = grouped.Key.Flag, 
            Total = 1 
           }; 

var reduce = from result in map 
        group result by result.Kind into g 
        select new 
        { 
         Kind = g.Key, 
         Total = g.Sum(c => c.Total) 
        }; 

var totalClients = reduce.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Buy.ToString())?.Total ?? 0; 
var totalSuppliers = reduce.FirstOrDefault(c => c.Kind == eSomeEnumFlag.Sell.ToString())?.Total ?? 0; 

totalClients = 2

totalSuppliers = 1,其右!

我在內存中手動映射/縮減代碼,完全相同,並且其工作方式與預期的完全相同。

我的索引有什麼問題?我錯過了什麼?在索引中使用group by有一些限制嗎?

在此先感謝。

我應該提到,在Map方法中,我用複合鍵進行了分組。所以Name和SomeEnumFlag應該像這兩個屬性之間的區別,有3個枚舉({某公司名稱,購買},另一個公司名稱Buy,另一個公司名稱Sell})。多少買? 2.多少賣? 1. Raven索引不起作用。在內存示例中,模擬map/reduce的行爲,可以正常工作。

+0

好的 - 我注意到的快速的事情:在您的第一個代碼示例中,您正在查詢結果的結果。然而,在你的第二個例子中,你說事情正確的地方,你正在查詢以前的變量「map」。這是一個簡單的錯字嗎? – prestonsmith

+0

是的,這是正確的,根據這個烏鴉文檔https://ravendb.net/docs/article-page/3.5/csharp/indexes/map-reduce-indexes。映射產生結果,然後我可以使用Reduce方法查詢結果。第二個通知,map是一個模擬Map方法的變量,所以map有一個分組查詢。我的索引和烏鴉文檔之間的唯一區別是Map funcion中的分組。 – user1203003

回答

0

我不認爲你的索引有什麼問題,我認爲你的LINQ查詢存在問題。

假設只有3個項目,也許試試這個查詢呢?

var totalSuppliers = reduce.Count(c => c.Kind == eSomeEnumFlag.Buy.ToString()) 

這縮短了我的想法,使得邏輯更加清晰,應該讓你找到你想要的東西?如果不讓我知道,我會深入探討一下。

+0

我使用的示例只有3個項目,但在生產中有數十萬個,目標是在儀表板中顯示用戶擁有多少個供應商和客戶。你從我的示例中回答使用減少變量,這意味着我使用的內存方法,但我有數千個文檔。所以我想我應該在加載儀表板頁面時使用索引來快速響應。 – user1203003

+0

啊我的錯誤 - 現在再次檢查您的原始代碼 – prestonsmith