gpt4 book ai didi

c# - mongoDB upsert 数组

转载 作者:可可西里 更新时间:2023-11-01 09:24:43 28 4
gpt4 key购买 nike

我的数据库模型是这样的

"clientId":"123456"
"devices" :
[{
"deviceId" : "123",
"deviceType" : "ios",
"notification" : true,
}
{
"deviceId" : "321",
"deviceType" : "android",
"notification" : true,

}
]

我传递给我的数据库方法的 C# 模型有 ClientId、DeviceId、DeviceType、notification。请注意,它没有设备阵列

我要实现的行为

  1. (工作)如果 ClientId 尚未在数据库中,则使用传递的值在数据库中创建一条新记录,(设备数组将有一个元素)

  2. 如果数据库中已经找到ClientId,则根据以下规则更新记录:

    2.1 如果设备数组不包含 DeviceId,则使用传递的值向数组添加一个新元素

    2.2 如果设备数组已经包含 DeviceId 更新元素的设备类型和通知。

我正在使用 C#。任何帮助表示赞赏

示例:给定上述数据库状态,通过传递 clientId:123456,deviceId 321 deviceType“kindle”,通知“false”,数据库将更改为

"clientId":"123456"
"devices" :
[{
"deviceId" : "123",
"deviceType" : "ios",
"notification" : true,
}
{
"deviceId" : "321",
"deviceType" : "kindle",
"notification" : false,

}
]

最佳答案

这并不像您想象的那么简单,实际上有趣的是您将对此的分析分为三个部分。因为,你猜怎么着?这正是您必须做的。让我们考虑以下步骤:

1。如果文档不存在则插入一个文档

db.collection.update(
{
"clientId":"123456"
},
{
"$setOnInsert": {
"clientId": "123456",
"devices": [{
"deviceId": "321",
"deviceType" : "kindle",
"notification" : false
}]
}
},
{ "upsert": true }
)

因此,您要做的是插入一个新文档,其中当前不存在“clientId”。这可以作为“upsert”来完成,以避免可能的唯一键冲突,甚至在没有“唯一”约束的情况下,这样的“upsert”性质确保您只在找不到"new"文档时创建它。这里还有 $setOnInsert,因为您不想对此时“找到”的文档做任何事情。

注意这里没有尝试匹配数组中的元素。这是因为您可能不想仅仅因为现有文档没有“那个”数组元素而“创建”一个新文档。这让我们进入下一步。

2。更新文档中确实存在的内容

db.collection.update(
{
"clientId":"123456",
"devices": { "$elemMatch": { "deviceId" : "321" } }
},
{
"$set": {
"devices.$.deviceType" : "kindle",
"devices.$.notification" : false
}
}
)

现在,您实际上想要尝试“匹配”文档中的“clientId”,该文档确实包含数组中的一个元素,该元素也与您正在寻找的“deviceId”相匹配。因此,通过指定要匹配的条件,您可以使用位置 $ 运算符来将字段设置在“匹配”位置。

如上所述,这将匹配一个没有,因此更新完成或未完成。所以这就转到我们级联的最后一部分:

3。在不存在的地方添加数组元素

db.collection.update(
{
"clientId":"123456"
},
{
"$addToset": { "devices": {
"deviceId" : "321",
"deviceType" : "kindle",
"notification" : false
}}
}
)

所以这是重要的最后阶段。原因是如果前面的操作确实“创建”或“更新”了现有文档,那么这里使用$addToSet 可以确定 您不是将另一个文档“推送”到具有相同“deviceId”但其他不同值的数组。如果这些阶段中的一个起作用,那么这将看到该元素的所有值都已经存在,并且不会再添加另一个。

如果您尝试以不同的顺序执行此操作,在您呈现的情况下,数组中将有两个文档,它们具有相同的“deviceId”,但“deviceType”和“通知”。这就是它排在最后的原因。

结论

很遗憾,没有简单的方法将它们组合成一个操作。运算符根本不存在,所以这可以在单个语句中完成,因此您必须执行三个更新操作才能执行您想要的操作。另外如前所述,应用这些更新的顺序重要,以便您获得所需的结果。

虽然这在当前的“生产”版本中尚不存在,但即将发布的版本(撰写本文时为 2.6 及更高版本)确实有一种方法可以使用 "batch" 的新语法来 update 这些请求:

db.runCommand(
"update": "collection",
"updates": [
{
"q": { "clientId":"123456" },
"u": {
"$setOnInsert": {
"clientId": "123456",
"devices": [{
"deviceId": "321",
"deviceType" : "kindle",
"notification" : false
}]
},
"upsert": true
},
{
"q": {
"clientId":"123456",
"devices": { "$elemMatch": { "deviceId" : "321" } }
},
"u": {
"$set": {
"devices.$.deviceType" : "kindle",
"devices.$.notification" : false
}
}
},
{
"q": { "clientId":"123456" },
"u": {
"$addToset": { "devices": {
"deviceId" : "321",
"deviceType" : "kindle",
"notification" : false
}}
}
}
]
)

因此,虽然那仍然本质上是三个操作,但至少您可以通过网络将它们发送一次

关于c# - mongoDB upsert 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22664972/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com