如何在单次调用中根据条件更新不同字段

问题描述 投票:0回答:1
public class Job
{
    public Guid Id { get; set; }

    public bool IsPending { get; set; }

    public bool IsComplete { get; set; }
}

我有两个名为

List<Guid> A
List<Guid>B
的 Id 列表。

对于

List A
,我想设置
Update.Set("IsPending", True)

对于

List B
,我想设置
Update.Set("IsComplete", True)

我可以通过两次数据库调用来实现这一点:

this.UpdateManyAsync(Builders<Job>.Filter.In(f => f.Id, A), Builders<Job>.Update.Set(x => x.IsPending, true), cancellationToken: cancellationToken)

第二个调用为

this.UpdateManyAsync(Builders<Job>.Filter.In(f => f.Id, B), Builders<Job>.Update.Set(x => x.IsComplete, true), cancellationToken: cancellationToken)

是否可以在单个数据库调用中实现?

c# .net mongodb mongodb-query mongodb-.net-driver
1个回答
1
投票

我认为不可能实现 Fluent Api,因为 MongoDB .NET 驱动程序不支持第二个参数为

Set
Expression
方法。这些是可用的方法:

public UpdateDefinition<TDocument> Set<TField>(FieldDefinition<TDocument, TField> field, TField value)
public UpdateDefinition<TDocument> Set<TField>(Expression<Func<TDocument, TField>> field, TField value)

为了实现您的要求,您可以使用聚合管道作为

BsonDocument[]
Builders<Job>.Update.Pipeline()
传递更新查询。

注意,在 MongoDB 文档中,我将 Guid 值存储为字符串类型,因此需要指定 Guid 序列化的映射规则,并将 Guid 转换为字符串才能使查询有效。

using MongoDB.Bson.Serialization.Serializers;

BsonClassMap.RegisterClassMap<Job>(
    map =>
    {
        map.AutoMap();
        map.MapProperty(x => x.Id).SetSerializer(new GuidSerializer(BsonType.String));
    });

UpdateDefinition<Job> update = Builders<Job>.Update.Pipeline(new BsonDocument[]
{
    new BsonDocument("$set",
        new BsonDocument
        {
            {
                "IsPending",
                new BsonDocument("$cond",
                    new BsonDocument
                    {
                       {
                            "if",
                            new BsonDocument(
                                "$in", 
                                new BsonArray
                                {
                                    "$_id",
                                    BsonArray.Create(A.Select(x => x.ToString()).ToList())
                                }
                            )
                        },
                        { "then", true },
                        { "else", "$IsPending" }
                    }
                )
            },
            {
                "IsComplete",
                new BsonDocument("$cond",
                    new BsonDocument
                    {
                       {
                            "if",
                            new BsonDocument(
                                "$in", 
                                new BsonArray
                                {
                                    "$_id",
                                    BsonArray.Create(B.Select(x => x.ToString()).ToList())
                                }
                            )
                        },
                        { "then", true },
                        { "else", "$IsComplete" }
                    }
                )
            }
        }
    )
});

演示

© www.soinside.com 2019 - 2024. All rights reserved.