假设我有一个典型的客户和订单方案。我有一组客户,每个客户文档都有一个订单列表。现在我想查询订单日期在上周内的客户,即大于DateTime.UtcNow.AddDays(-7)且小于DateTime.UtcNow。
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;
有没有更好的方法来实现这一目标?
答案 0 :(得分:1)
作为一般的规则,我不会在客户中嵌入订单。在没有获取所有订单的情况下找到所有客户似乎是一个非常自然的查询。此外,订单通常具有相当复杂的生命周期,并且代表长期运行的业务交易,因此它们值得单独的文档。
当然,这取决于您的确切要求,但客户是如此重要,以至于您可以争辩还嵌入付款,查询,取消,发票以及基本上与客户相关的任何其他业务交易以某种方式,所以你最终将所有数据填入一个无法管理的集合中。
在任何情况下,都可以更轻松地查询db.Orders.find({"OrderDate" : {$gt : lastWeek} });
,然后使用$in
运算符通过Order.CustomerId
查找客户。
如果上周的订单数量很大(例如> 10,000),则在客户中引入MostRecentOrder
字段或使用map / reduce是有意义的。也可以对订单进行分页,然后在生成的较小大小的块上使用$in
运算符。如果您这样做,请确保按照OrderDate
。