2

典型的な顧客と注文のシナリオがあるとします。顧客のコレクションがあり、各顧客ドキュメントには注文のリストがあります。ここで、注文日が先週以内の顧客、つまり 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;

これを達成するためのより良い方法はありますか?

4

1 に答える 1

1

ほぼ原則として、私は顧客に注文を埋め込みません。これまでに行ったすべての注文を取得せずにすべての顧客を見つけることは、非常に自然なクエリのようです。また、注文は通常、かなり複雑なライフサイクルを持ち、長期にわたるビジネストランザクションを表すため、別のドキュメントの価値があります。

もちろん、これはあなたの正確な要件に少し依存しますが、顧客は非常に中心的であるため、支払い、問い合わせ、キャンセル、請求書、および基本的に何らかの方法で顧客に関連する他のビジネストランザクションも埋め込むことを主張できます。最終的に、すべてのデータを1つの管理できないコレクションに詰め込みます。

いずれの場合も、クエリを実行してから、演算子をdb.Orders.find({"OrderDate" : {$gt : lastWeek} });使用してを介して顧客を見つける方が簡単です。$inOrder.CustomerId

MostRecentOrder先週の注文数が多い場合(たとえば> 10,000)、顧客にフィールドを紹介するか、代わりにmap/reduceを使用するのが理にかなっています。注文をページ分割し$inて、結果として得られる小さなサイズのチャンクに対して演算子を使用することもできます。その場合は、のような安定した基準で並べ替えてOrderDateください。

于 2013-03-21T15:23:58.520 に答える