2017-02-09 2 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 by 인덱스를 사용할 때 몇 가지 제한이 있습니까?

미리 감사드립니다.

Map 메서드에서 복합 키를 사용하여 그룹화했음을 언급해야합니다. 따라서 Name과 SomeEnumFlag는 3 개의 전체 열거 형 ({일부 회사 이름, Buy}, {다른 회사 이름, Buy}, {Another company name, Sell})과 함께이 두 속성 사이의 별개처럼 작동해야합니다. 얼마나 많은 구매? 2. 얼마나 많이 판매합니까? 1. 레이븐 인덱스가 작동하지 않습니다. map/reduce의 동작을 시뮬레이트하는 메모리 샘플에서 잘 동작합니다.

+0

Ok - 내가 알아 차 렸던 것 : 첫 번째 코드 샘플에서 결과에 대한 쿼리를 수행하고 있습니다. 그러나 두 번째 예에서 상황이 올바르게 진행된다고 말하면 이전 변수 인 "map"을 쿼리합니다. 그건 단순한 오타 였나요? – prestonsmith

+0

그래,이 까마귀 문서 https://ravendb.net/docs/article-page/3.5/csharp/indexes/map-reduce-indexes에 따르면 맞습니다. 결과를 매핑하면 Reduce 메서드에서 결과를 쿼리 할 수 ​​있습니다. 두 번째 공지 인 map은 Map 메소드를 시뮬레이트하는 변수이므로 map에는 그룹화 쿼리가 있습니다. 색인과 까마귀 문서의 유일한 차이는지도 기능의 그룹입니다. – user1203003

답변

0

인덱스에 문제가 있다고 생각하지 않습니다. LINQ 쿼리에 문제가 있다고 생각합니다.

3 개 항목 만 있다고 가정하면이 쿼리를 대신 사용해보십시오.

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

이렇게하면 로직이 더 명확 해지고 생각하게됩니다. 원하는 것을 얻을 수 있을까요? 나에게 알려주지 않으면 좀 더 자세히 조사 할 것입니다.

+0

내가 사용한 샘플에는 단 3 개 항목이 있지만 프로덕션에서는 수십만 가지가 있으며 목표는 대시 보드에 사용자가 보유한 공급 업체 및 클라이언트 수를 표시하는 것입니다. 당신은 내 샘플에서 변수를 사용하여 대답, 그게 내가 사용하는 메모리 접근 방식을 의미하지만, 수천명의 의사를 생각해. 따라서 대시 보드 페이지를로드 할 때 빠른 응답을 위해 색인을 사용해야한다고 생각합니다. – user1203003

+0

아, 내 실수 - 원래 코드를 다시 검토하십시오. – prestonsmith

관련 문제