2013-03-21 184 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這樣的穩定​​標準進行排序。