2つ以上のフィールドをmongoDbc#ドライバーと組み合わせた式でフィルター/ソートするにはどうすればよいですか?

クリスチャングリソリア

モデルとして次のようなものがあると仮定します。

public abstract class BaseModel
{
    public DateTime CreatedDT { get; set; }
    public DateTime? ModifiedDT { get; set; }
}

public class Model : BaseModel
{
   //more properties here
}

MongoDbドライバー用に作成されたこのLinqクエリと同等のものが欲しいです。

var collection = database.GetCollection<Model>("CollectionName");
var result = await collection.Find(FilterDefinition<Model>.Empty).ToListAsync();
result.Where(m => m.ModifiedDT ?? m.CreatedDT > someDate).OrderBy(m => m.ModifiedDT ?? m.CreatedDT).ToList();
            

私はこれを試しました:

var collection = database.GetCollection<Model>("CollectionName");
var result = await collection.Find(x => m.ModifiedDT ?? m.CreatedDT > someDate)
                .SortBy(m => m.ModifiedDT ?? m.CreatedDT)
                .ToListAsync();

しかし、私は得る:

System.InvalidOperationException:m => Convert((m.ModifiedDT ?? m.CreatedDT)、Object)のシリアル化情報を判別できません。

ケビン・スミス

この種類のクエリでは、nullであることに基づいて1つのフィールドまたは他のフィールドを選択するための集計クエリが必要になります。これの演算子はで$ifnullあり、$addFieldsステージを使用してこれをドキュメントに追加できます

C#でこれを行う方法の例を以下に示します。現時点では、ドライバーにはフィールドを追加するための流暢な方法がサポートされていないため、手動で追加する必要があります。 AppendStage

var client = new MongoClient();
var db = client.GetDatabase("db");
var collection = db.GetCollection<Order>("orders");

// Clean out database to start off with.
await db.DropCollectionAsync(collection.CollectionNamespace.CollectionName);

var date = DateTime.UtcNow.AddMinutes(-1);

// Add some data where some ModifiedDT are null
await collection.InsertManyAsync(new[]
{
    new Order{ Name = "1", CreatedDT = DateTime.UtcNow.AddMinutes(1), ModifiedDT = null},
    new Order{ Name = "2", CreatedDT = date, ModifiedDT = DateTime.UtcNow.AddMinutes(2)},
    new Order{ Name = "3", CreatedDT = DateTime.UtcNow.AddMinutes(3), ModifiedDT = null},
    new Order{ Name = "4", CreatedDT = date, ModifiedDT = DateTime.UtcNow.AddMinutes(4)},
    new Order{ Name = "5", CreatedDT = DateTime.UtcNow.AddMinutes(5), ModifiedDT = null},
    new Order{ Name = "6", CreatedDT = date, ModifiedDT = DateTime.UtcNow.AddMinutes(6)},
});
var someDate = DateTime.UtcNow.AddDays(-10);
var orders = collection.Aggregate()
    // Add a aggregation stage to add an extra field to the document of LastModified which is either ModifiedDT, but if null $CreatedDT
    .AppendStage<OrderProjection>(
        @"{ $addFields: { LastModified: { $ifNull: [ ""$ModifiedDT"", ""$CreatedDT"" ] } } }")
    // Match when our new field is greater than a given date.
    .Match(x => x.LastModified > someDate)
    // Sort by our new field of LastModified
    .SortBy(x => x.LastModified)
    // Remove the field we added so we don't transfer it back over the wire
    .AppendStage<Order>(@"{ $unset: ""LastModified"" }")
    // Execute the aggregation query
    .ToList();


foreach (var order in orders)
{
    Console.WriteLine($"Name: {order.Name}");
}
// Name: 1
// Name: 2
// Name: 3
// Name: 4
// Name: 5
// Name: 6

internal class Order
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedDT { get; set; }
    public DateTime? ModifiedDT { get; set; }
}

internal class OrderProjection
{
    public ObjectId Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedDT { get; set; }
    public DateTime LastModified { get; set; }
    public DateTime? ModifiedDT { get; set; }
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ