モデルとして次のようなものがあると仮定します。
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]
コメントを追加