简体   繁体   English

使用 C# 驱动更新 MongoDB 中的多项数组

[英]Update multi items of array in MongoDB using C# Driver

I have a document like this sample:我有一个像这个样本的文件:

    [
{ 
"_id" : "id1",     
"items" : [
    {
        "_id" : "f449dc0b-3d1b-4a59-b622-6a42ce10b147",
        "token" : "aaa",  
        "isExpired" : false, 
        "expiredAt" : ISODate("")
    }, 
    {
        "_id" : "3d1497d7-f74c-4d88-b15c-bf2f9c736374", 
        "token" : "bbb",  
        "isExpired" : false, 
        "expiredAt" : ISODate("")
    }, 
    {
        "_id" : "6e827e2a-5a25-4343-b646-885816bb8cc4", 
        "token" : "ccc",  
        "isExpired" : false, 
        "expiredAt" : ISODate("")
    }]
},
...,
...
]

If I have the _id of the document and a token of the items, How can I expire every item except given token ?如果我有文档的_id和项目的token ,我怎样才能使除给定令牌之外的每个项目都过期?

For example, if the document id is "id1" and the token is "aaa" , I want the "bbb" and "ccc" tokens to expire.例如,如果文档 id 是"id1"并且令牌是"aaa" ,我希望"bbb""ccc"令牌过期。

I prefer the operation to be done with a single query and without replacing the entire document or array.我更喜欢使用单个查询来完成操作,而无需替换整个文档或数组。

My code is something like this, but only one item expires each time:我的代码是这样的,但每次只有一项过期:

var filter = Builders<Document>.Filter
.And(
    Builders<Document>.Filter.Eq(d => d.Id, "id1"), 
    Builders<Document>.Filter.ElemMatch(d => d.items, item => item.token != "aaa"));

var update = Builders<Document>.Update
            .Set(x => x.items[-1].isExpired, true)
            .Set(x => x.items[-1].expiredAt, DateTime.UtcNow);

So to start with I'm going to insert the sample record you have give but have the expiredAts all to null.因此,首先我将插入您提供的示例记录,但将 expiredAts 全部插入 null。

> db.test.insert({
    "_id" : "id1",
    "items" : [
        {
            "_id" : "f449dc0b-3d1b-4a59-b622-6a42ce10b147",
            "token" : "aaa",
            "isExpired" : false,
            "expiredAt" : null
        },
        {
            "_id" : "3d1497d7-f74c-4d88-b15c-bf2f9c736374",
            "token" : "bbb",
            "isExpired" : false,
            "expiredAt" : null
        },
        {
            "_id" : "6e827e2a-5a25-4343-b646-885816bb8cc4",
            "token" : "ccc",
            "isExpired" : false,
            "expiredAt" : null
        }]
    })
WriteResult({ "nInserted" : 1 })

Now for the C# we need to take advantage of the array filters as a normal find can either update one item in an array (with the positional $ ) or update all items in an array (with the all positional operator $[] ).现在对于 C#,我们需要利用数组过滤器,因为正常查找可以更新数组中的一项(使用位置$ )或更新数组中的所有项(使用所有位置运算符$[] )。

var client = new MongoClient();

var db = client.GetDatabase("test");
var collection = db.GetCollection<Document>("test");


var filter = Builders<Document>.Filter.Eq(d => d.Id, "id1");

var update = Builders<Document>.Update
    .Set("items.$[i].isExpired", true)
    .Set("items.$[i].expiredAt", DateTime.UtcNow);

var arrayFilterDefinitions = new ArrayFilterDefinition[]
{
    new BsonDocumentArrayFilterDefinition<Item>(BsonDocument.Parse(@"{ ""i.token"" : { $ne: ""aaa"" } }"))
};
await collection.UpdateOneAsync(filter, update, new UpdateOptions{ArrayFilters = arrayFilterDefinitions});

Executing the above will just update the items in the array where the token is not "aaa".执行上述操作只会更新数组中令牌不是“aaa”的项目。

More information can be found on the MongoDB documentation - https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#identifier有关更多信息,请参阅 MongoDB 文档 - https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#identifier

> db.test.findOne()
{
        "_id" : "id1",
        "items" : [
                {
                        "_id" : "f449dc0b-3d1b-4a59-b622-6a42ce10b147",
                        "token" : "aaa",
                        "isExpired" : false,
                        "expiredAt" : null
                },
                {
                        "_id" : "3d1497d7-f74c-4d88-b15c-bf2f9c736374",
                        "token" : "bbb",
                        "isExpired" : true,
                        "expiredAt" : ISODate("2020-08-13T15:57:00.582Z")
                },
                {
                        "_id" : "6e827e2a-5a25-4343-b646-885816bb8cc4",
                        "token" : "ccc",
                        "isExpired" : true,
                        "expiredAt" : ISODate("2020-08-13T15:57:00.582Z")
                }
        ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM