C# 阵列上的mongoDB upsert
我的db模型是这样的C# 阵列上的mongoDB upsert,c#,arrays,mongodb,mongodb-query,C#,Arrays,Mongodb,Mongodb Query,我的db模型是这样的 "clientId":"123456" "devices" : [{ "deviceId" : "123", "deviceType" : "ios", "notification" : true, } { "deviceId" : "321", "deviceType" : "android", "notification" : true, } ] 我传递给DB方法的c#模型有Cl
"clientId":"123456"
"devices" :
[{
"deviceId" : "123",
"deviceType" : "ios",
"notification" : true,
}
{
"deviceId" : "321",
"deviceType" : "android",
"notification" : true,
}
]
我传递给DB方法的c#模型有ClientId、DeviceId、DeviceType和notification。请注意,它没有设备阵列
我想要达到的行为
"clientId":"123456"
"devices" :
[{
"deviceId" : "123",
"deviceType" : "ios",
"notification" : true,
}
{
"deviceId" : "321",
"deviceType" : "kindle",
"notification" : false,
}
]
您正在寻找一个典型的位置运算符情况:
db.coll.update
(
{
"clientId":"123456","devices.deviceId":"321"
},
{
$set:
{
"devices.$.deviceType":"kindle","devices.$.notification":"false"
}
}
)
您需要更新数组中匹配的元素,$可以为您执行此操作,这样您就可以在数组中找到具有特定元素的文档,并使用位置运算符$来“记住”要更新的元素。这并不像您想象的那么简单,事实上,有趣的是,你把你的分析分为三个部分。因为,你猜怎么着?这正是你必须做的。让我们考虑以下步骤: 1.如果文档不存在,请插入文档
db.collection.update(
{
“客户ID”:“123456”
},
{
“$setOnInsert”:{
“客户ID”:“123456”,
“设备”:[{
“设备ID”:“321”,
“设备类型”:“kindle”,
“通知”:虚假
}]
}
},
{“upsert”:true}
)
因此,您要做的是在当前不存在“clientId”的地方插入一个新文档。这可以作为“向上插入”来完成,以避免可能的唯一关键点冲突,即使在没有“唯一”约束的情况下,也可以使用“向上插入”来确保仅在未找到“新”文档时创建该文档。这里还有$setOnInsert
,因为您不想对此时“找到”的文档执行任何操作
请注意,没有尝试匹配数组中的元素。这是因为您可能不想仅仅因为现有文档没有“that”数组元素而“创建”新文档。这让我们进入下一步
2.在文档存在的地方更新文档的内容
db.collection.update(
{
“客户ID”:“123456”,
“设备”:{“$elemMatch”:{“设备ID”:“321”}
},
{
“$set”:{
“设备.$.deviceType”:“kindle”,
“设备.$.notification”:false
}
}
)
现在,您需要实际尝试“匹配”文档中的“clientId”,该“clientId”在数组中包含一个元素,该元素也与您要查找的“deviceId”匹配。因此,通过指定要匹配的条件,可以使用positional$
操作符将字段设置为“匹配”位置
如上所述,这要么匹配一件事情,要么什么都不匹配,因此要么更新完成了,要么没有。这就转到了级联的最后一部分:
3.将数组元素添加到不存在的位置
db.collection.update(
{
“客户ID”:“123456”
},
{
“$addToset”:{“设备”:{
“设备ID”:“321”,
“设备类型”:“kindle”,
“通知”:虚假
}}
}
)
因此,这是非常重要的最后阶段。原因是,如果前面的操作之一确实“创建”或“更新”了现有文档,那么在此处使用$addToSet
可以确保您没有使用相同的“deviceId”但其他不同的值将另一个文档“推送”到数组中。如果这些阶段中有一个有效,那么这将看到该元素的所有值都已存在,并且不会再添加另一个值
如果您尝试以不同的顺序执行此操作,那么在您呈现的情况下,数组中会有两个文档,它们具有相同的“deviceId”,但“deviceType”和“notification”的值不同。这就是为什么它排在最后
结论
因此,不幸的是,没有简单的方法将这些操作组合为一个操作。运算符根本不存在,因此这可以在一条语句中完成,因此您必须执行三个更新操作才能完成所需的操作。同样如前所述,这些更新的应用程序的顺序非常重要,以便您获得所需的结果
虽然目前的“生产”版本中尚不存在这种情况,但即将发布的版本(2.6及更高版本,截至编写时)确实有办法使用新语法来处理这些请求,以便:
db.runCommand(
“更新”:“收集”,
“更新”:[
{
“q”:{“clientId”:“123456”},
“u”:{
“$setOnInsert”:{
“客户ID”:“123456”,
“设备”:[{
“设备ID”:“321”,
“设备类型”:“kindle”,
“通知”:虚假
}]
},
“向上插入”:正确
},
{
“q”:{
“客户ID”:“123456”,
“设备”:{“$elemMatch”:{“设备ID”:“321”}
},
“u”:{
“$set”:{
“设备.$.deviceType”:“kindle”,
“设备.$.notification”:false
}
}
},
{
“q”: