3 回答
TA贡献1851条经验 获得超3个赞
不幸的是,这不能在使用 anupsert或类似的单个更新语句中完成。
这可以使用从MongoDB 3.2开始支持的bulkWrite()来实现。
您还可以使用MongoDB 4.2 中的新update()命令 - 请注意,这仅在 4.2 中可用。
update 命令现在允许多个更新语句。虽然您可能必须运行两个更新命令,但您只需要发送一次命令并让 MongoDB 为您批处理语句。
鉴于您的要求,您可以尝试以下操作,首先尝试使用$ 位置运算符更新数组中的相关元素。
然后我们使用$addToSet数组运算符,它将尝试添加一个新的数组元素 - 只有在没有找到适合我们的场景的匹配数组元素时,在步骤 1 中无法进行更新。
这两种解决方案都适用于您的场景。
使用 bulkWrite()
db.getCollection("tests").bulkWrite([
{
updateOne: {
filter: {link: "abc.com", "Values.valueID": "v2"},
update: {$set: {"Values.$.value": "xyz"}}
}
},
{
updateOne: {
filter: {link: "abc.com"},
update: {
$addToSet: {
"Values": {
"valueID": "v2",
"date": "05-07-2015",
"value": "xyz"
}
}
}
}
}
]);
使用新的 update() 命令:
db.runCommand(
{
update: "tests",
updates: [
{
q: {link: "abc.com", "Values.valueID": "v2"},
u: {$set: {"Values.$.value": "xyz"}}
},
{
q: {link: "abc.com"},
u: {
$addToSet: {
"Values": {
"valueID": "v2",
"date": "05-07-2015",
"value": "xyz"
}
}
}
}
],
ordered: false,
writeConcern: {w: "majority", wtimeout: 5000}
}
)
样本数据:
db.getCollection("tests").insertMany([{
"link": "abc.com",
"Values": [
{
"valueID": "v1",
"date": "05-07-2015",
"value": "10"
}
]
},
{
"link": "def.com",
"Values": [
{
"valueID": "v1",
"date": "05-07-2015",
"value": "1"
}
]
}]
);
不存在时插入数组:
db.runCommand(
{
update: "tests",
updates: [
{
q: {link: "abc.com", "Values.valueID": "v2"},
u: {$set: {"Values.$.value": "xyz"}}
},
{
q: {link: "abc.com"},
u: {
$addToSet: {
"Values": {
"valueID": "v2",
"date": "05-07-2015",
"value": "xyz"
}
}
}
}
],
ordered: false,
writeConcern: {w: "majority", wtimeout: 5000}
}
)
结果:
{
"_id" : ObjectId("5dd8164969f4361ce9821b88"),
"link" : "abc.com",
"Values" : [
{
"valueID" : "v1",
"date" : "05-07-2015",
"value" : "20"
},
{
"valueID" : "v2",
"date" : "05-07-2015",
"value" : "xyz"
}
]
}
更新现有值:
db.runCommand(
{
update: "tests",
updates: [
{
q: {link: "abc.com", "Values.valueID": "v2"},
u: {$set: {"Values.$.value": "new value"}}
},
{
q: {link: "abc.com"},
u: {
$addToSet: {
"Values": {
"valueID": "v2",
"date": "05-07-2015",
"value": "new value"
}
}
}
}
],
ordered: false,
writeConcern: {w: "majority", wtimeout: 5000}
}
)
结果:
{
"_id" : ObjectId("5dd8164969f4361ce9821b88"),
"link" : "abc.com",
"Values" : [
{
"valueID" : "v1",
"date" : "05-07-2015",
"value" : "20"
},
{
"valueID" : "v2",
"date" : "05-07-2015",
"value" : "new value"
}
]
}
TA贡献1851条经验 获得超5个赞
MongoDB 4.2
使用聚合管道更新
从 MongoDB 4.2开始,db.collection.update()方法可以接受指定要执行的修改的聚合管道[ stage1, stage2, ... ]。
所以这里$reduce有一些$condition 的运算符可以解决问题。
db.getCollection("ashish2").update(
//filter criteria for the update operation
{ },
[{ "$set": {
"Values": {
"$reduce": {
"input": "$Values",
"initialValue": [],
"in": {
"$concatArrays": [
"$$value",
{
"$cond": [
// Here you can select your value with which you want to match
{ "$eq": ["$$this.valueID", "v2"] },
// Updation after match
[{ "valueID": "v1", "date": "05-07-2015", "value": "20" }],
// Updation when doesn't match
{
"$concatArrays": [
[{ "valueID": "v1", "date": "05-07-2015", "value": "20" }],
["$$this"]
]
}
]
}
]
}
}
}
}}]
)
TA贡献1801条经验 获得超15个赞
看看 $addToSet 运算符
$addToSet 运算符向数组添加一个值,除非该值已经存在,在这种情况下 $addToSet 对该数组不做任何事情。
https://docs.mongodb.com/manual/reference/operator/update/addToSet/index.html
添加回答
举报