更新数组中的对象或使用唯一字段插入数组
Update an object in array or insert into the array using a unique field
我有一个文档,其中包含一个包含对象元素的数组 属性。
例如
{
"_id": "61c01098bc29520008efc00f",
"name": "codedump",
"employments": [
{
"type": "PERMANENT",
"salary": 1000000000
},
{
"type": "TEMP",
"salary": 1000000000
},
{
"type": "PART_TIME",
"salary": 1000000000
},
]
}
并且在使用 type
更新就业工资时,如果该类型已经在就业中,那么我只需要更新 salary
。否则我需要将新项目推送到数组。我正在尝试找到一种方法来在单个查询中完成这项工作。
- 如果类型已经存在于数组中(用于更新):
/// Update data:
{
"type": "PERMANENT",
"salary": 10
}
// For this case I want the example document to become:
{
"_id": "61c01098bc29520008efc00f",
"name": "codedump",
"employments": [
{
"type": "PERMANENT",
"salary": 10 // From 1000000000 to 10
},
{
"type": "TEMP",
"salary": 1000000000
},
{
"type": "PART_TIME",
"salary": 1000000000
},
]
}
- 如果类型不存在:
/// Update data:
{
"type": "INVESTMENT",
"salary": 10000
}
// For this case I want the example document to become:
{
"_id": "61c01098bc29520008efc00f",
"name": "codedump",
"employments": [
{
"type": "PERMANENT",
"salary": 1000000000
},
{
"type": "TEMP",
"salary": 1000000000
},
{
"type": "PART_TIME",
"salary": 1000000000
},
{
"type": "INVESTMENT",
"salary": 10000
}
]
}
不知道你要的是不是一次操作就可以...
话虽如此,我会怎么做,使用 $
位置运算符来更新我想要的数组元素。 Doc & playground.
db.collection.update({
"employments.type": "PERMANENT",
},
{
"$set": {
"employments.$.salary": 10
}
},
{
"multi": false,
"upsert": false
})
此操作仅在元素存在于数组中时有效。如果不是,则操作将失败。然后您可以在代码中捕获异常并使用 $push
执行插入。 Playground
db.collection.update({},
{
"$push": {
"employments": [
{
"type": "INVESTMENT",
"salary": 10000
}
]
}
},
{
"multi": false,
"upsert": false
})
技术上可以在 1 次调用中实现,从 Mongo v4.2 开始你可以使用 pipelined updates,这实际上允许你在更新主体中使用聚合运算符,因此你可以实现很多任何东西。
我会说,但它绝对不是很有效,这实际上取决于您想要 maximize/minimize(网络/数据库负载等)系统的哪一部分。
您可以这样做:
const input = {
"type": "INVESTMENT",
"salary": 10000
}
db.collection.update({},
[
{
$set: {
employments: {
$cond: [
{
$in: [
input.type,
"$employments.type"
]
},
{
$map: {
input: "$employments",
in: {
$cond: [
{
$eq: [
"$$this.type",
input.type,
]
},
{
type: "$$this.type",
salary: input.salary
},
"$$this"
]
}
}
},
{
$concatArrays: [
"$employments",
[
input
]
]
}
]
}
}
}
])
我有一个文档,其中包含一个包含对象元素的数组 属性。
例如
{
"_id": "61c01098bc29520008efc00f",
"name": "codedump",
"employments": [
{
"type": "PERMANENT",
"salary": 1000000000
},
{
"type": "TEMP",
"salary": 1000000000
},
{
"type": "PART_TIME",
"salary": 1000000000
},
]
}
并且在使用 type
更新就业工资时,如果该类型已经在就业中,那么我只需要更新 salary
。否则我需要将新项目推送到数组。我正在尝试找到一种方法来在单个查询中完成这项工作。
- 如果类型已经存在于数组中(用于更新):
/// Update data:
{
"type": "PERMANENT",
"salary": 10
}
// For this case I want the example document to become:
{
"_id": "61c01098bc29520008efc00f",
"name": "codedump",
"employments": [
{
"type": "PERMANENT",
"salary": 10 // From 1000000000 to 10
},
{
"type": "TEMP",
"salary": 1000000000
},
{
"type": "PART_TIME",
"salary": 1000000000
},
]
}
- 如果类型不存在:
/// Update data:
{
"type": "INVESTMENT",
"salary": 10000
}
// For this case I want the example document to become:
{
"_id": "61c01098bc29520008efc00f",
"name": "codedump",
"employments": [
{
"type": "PERMANENT",
"salary": 1000000000
},
{
"type": "TEMP",
"salary": 1000000000
},
{
"type": "PART_TIME",
"salary": 1000000000
},
{
"type": "INVESTMENT",
"salary": 10000
}
]
}
不知道你要的是不是一次操作就可以...
话虽如此,我会怎么做,使用 $
位置运算符来更新我想要的数组元素。 Doc & playground.
db.collection.update({
"employments.type": "PERMANENT",
},
{
"$set": {
"employments.$.salary": 10
}
},
{
"multi": false,
"upsert": false
})
此操作仅在元素存在于数组中时有效。如果不是,则操作将失败。然后您可以在代码中捕获异常并使用 $push
执行插入。 Playground
db.collection.update({},
{
"$push": {
"employments": [
{
"type": "INVESTMENT",
"salary": 10000
}
]
}
},
{
"multi": false,
"upsert": false
})
技术上可以在 1 次调用中实现,从 Mongo v4.2 开始你可以使用 pipelined updates,这实际上允许你在更新主体中使用聚合运算符,因此你可以实现很多任何东西。
我会说,但它绝对不是很有效,这实际上取决于您想要 maximize/minimize(网络/数据库负载等)系统的哪一部分。
您可以这样做:
const input = {
"type": "INVESTMENT",
"salary": 10000
}
db.collection.update({},
[
{
$set: {
employments: {
$cond: [
{
$in: [
input.type,
"$employments.type"
]
},
{
$map: {
input: "$employments",
in: {
$cond: [
{
$eq: [
"$$this.type",
input.type,
]
},
{
type: "$$this.type",
salary: input.salary
},
"$$this"
]
}
}
},
{
$concatArrays: [
"$employments",
[
input
]
]
}
]
}
}
}
])