2013-03-21 1 views
2

일반적인 고객 및 주문 시나리오가 있습니다. 고객 컬렉션이 있고 각 고객 문서에는 주문 목록이 있습니다. 이제 주문 날짜가 지난 주 내에있는 고객에게 질문합니다. 즉, DateTime.UtcNow.AddDays (-7)보다 크고 DateTime.UtcNow보다 작습니다.MongoDb C# Linq 질의 및 콜렉션의 자식 객체 반환

var startDate = DateTime.UtcNow.AddDays(-7); 
var endDate = DateTime.UtcNow; 
var query = collection.AsQueryable<Customer>() 
    .Where(c => c.Orders.Any(o => o.OrderDate > startDate && o.OrderDate < endDate)) 
    .SelectMany(b => b.Orders); 

이 다음과 같은 오류가 발생합니다

System.NotSupportedException: The SelectMany query operator is not supported. 
at MongoDB.Driver.Linq.SelectQuery.TranslateMethodCall(MethodCallExpression methodCallExpression) in C:\\build\\mongo-csharp-driver\\Driver\\Linq\\Translators\\SelectQuery.cs:line 687 

나의 현재 솔루션은 꽤 불쾌한 :

var customers = 
    collection.AsQueryable<Customer>() 
     .Where(c => 
      c.Orders.Any(o => 
       o.OrderDate > startDate && 
       o.OrderDate < endDate)) 
     .ToList(); 

var results = new List<Order>(); 
foreach (var orders in customer.Select(c => 
    c.Orders.Where(o => 
     o.OrderDate > startDate && 
     o.OrderDate < endDate))) 
{ 
    results.AddRange(orders); 
} 

return results; 

이를 달성하기 위해 더 나은 방법이 있나요?

답변

1

거의 일반적인 규칙으로 고객에게 주문을 포함시키지 않습니다. 모든 고객이 을 찾지 못한 것은 매우 자연스러운 쿼리 인 것 같습니다.은 모든 주문을 가져 왔습니다. 또한 주문은 일반적으로 매우 복잡한 라이프 사이클을 가지며 장기간 진행되는 비즈니스 트랜잭션을 나타 내기 때문에 별도의 문서를 작성할 가치가 있습니다.

물론 이것은 약간의 요구 사항에 달려 있지만 고객은 지불, 문의, 취소, 청구서 및 기본적으로 다른 고객과 관련된 비즈니스 트랜잭션을 포함시킬 수도 있습니다. 모든 데이터를 하나의 관리 할 수없는 컬렉션에 채우게됩니다.

어쨌든 db.Orders.find({"OrderDate" : {$gt : lastWeek} });을 쿼리 한 다음 $in 연산자를 사용하여 Order.CustomerId을 통해 고객을 찾는 것이 더 쉽습니다.

지난주의 주문 수가 많으면 (예 :> 10,000) 고객에게 MostRecentOrder 필드를 소개하거나 map/reduce를 사용하는 것이 좋습니다. 주문에 페이지 매기기를 수행 한 다음 작은 크기의 결과 청크에 $in 연산자를 사용할 수도 있습니다. 그렇게한다면 OrderDate과 같은 안정적인 기준으로 정렬해야합니다.