c# - 使用 C# 驱动程序更新 MongoDB 中的多项数组
问题描述
我有一个像这个样本的文件:
[
{
"_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("")
}]
},
...,
...
]
如果我有_id
文档的和token
项目的,我怎样才能使除给定令牌之外的每个项目都过期?
例如,如果文档 id 是"id1"
,令牌是"aaa"
,我希望"bbb"
和"ccc"
令牌过期。
我更喜欢使用单个查询来完成操作,而无需替换整个文档或数组。
我的代码是这样的,但每次只有一项过期:
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);
解决方案
因此,首先我将插入您提供的示例记录,但将 expiredAts 全部设置为空。
> 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 })
现在对于 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});
执行上述操作只会更新数组中令牌不是“aaa”的项目。
更多信息可以在 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")
}
]
}
推荐阅读
- c# - 如何在 Visual Studio 中创建 xml 文件类型的数据库后端
- python - 如何使用 Visual Studio Code 终端调用函数
- c# - 比较对象时哪种设计模式合适
- c++ - 如何修复“QtCharts”库文件未找到/无法包含
? - pm2 - pm2:未知选项 `--run-as-user'
- javascript - 我想知道用户是在线还是离线,我的应用程序将主要离线工作
- android - adb.exe 不断崩溃,即使重新安装了所有 Android 组件
- java - 如何使用 Gradle 运行任务禁用 IntelliJ 来运行我的代码?
- swift - 如何在 SwiftUI 中检测点击手势位置?
- c# - 如何在实体框架中过滤重复项以最大程度地减少性能损失?