更新数组中存在的对象,如果不存在则Push



下面是我的示例文档

{
"_id" : "1",
"principal" : "Joe",
"classroom" : [
{
"grade" : "1",
"class" : "A",
"totalStudent" : 10.0
},
{
"grade" : "1",
"class" : "B",
"totalStudent" : 20.0
}
]
}

my goal is

  1. 当过滤器匹配时,增加TotalStudent。principal : "Joe", classroom.grade: "1" classroom.class: "A"
  2. 如果对象不存在,则将新对象推入教室,例如classroom.grade: "1" classroom.class: "C"

我的当前查询(这个工作与增量到存在对象)


db.getCollection("classsroom").updateOne(
{
pricipal: "Joe", 
"classroom": {$elemMatch: {"grade":"1","class": "A"}}        
},

{ $inc: { "classroom.$.totalStudent": 5 } },
{upsert: true}


)

期待结果

{
"_id" : "1",
"principal" : "Joe",
"classroom" : [
{
"grade" : "1",
"class" : "A",
"totalStudent" : 10.0
},
{
"grade" : "1",
"class" : "B",
"totalStudent" : 20.0
},
{
"grade" : "1",
"class" : "c",
"totalStudent" : 5.0
}
]
}

可以这样使用update/aggregation (4.2+):

db.collection.update({ "principal":"Joe" },
[
{
$addFields: {
x: {
$size: {
$filter: {
input: "$classroom",
as: "c",
cond: {
$and: [
{
$eq: [
"$$c.grade",
"1"
]
},
{
$eq: [
"$$c.class",
"A"
]
}
]
}
}
}
}
}
},
{
$addFields: {
classroom: {
$cond: [
{
"$ne": [
"$x",
0
]
},
{
$map: {
input: "$classroom",
in: {
$mergeObjects: [
"$$this",
{
$cond: [
{
$and: [
{
$eq: [
"$$this.grade",
"1"
]
},
{
$eq: [
"$$this.class",
"A"
]
}
]
},
{
totalStudent: {
$add: [
"$$this.totalStudent",
5
]
}
},
{}
]
}
]
}
}
},
{
$concatArrays: [
"$classroom",
[
{
"class": "C",
"grade": "1",
"totalStudent": 5
}
]
]
}
]
}
}
},
{
$unset: "x"
}
],
{
multi: true
})

解释道:

  1. 添加临时变量x,该变量包含匹配条件(grade="1",class="A")的元素计数

  2. 使用临时变量x检查数组是否包含匹配的元素,如果x=0(没有元素匹配)执行concatArrays[]添加新元素。如果x>0(至少有1x个元素匹配),则更新totalStudent值,并添加所需的增量量。

  3. 使用$unset删除临时变量

  4. 添加multi:true对集合中所有匹配的文档执行操作

  5. 游乐场

改进版本(使用$let作为临时变量x):

Playground2

相关内容

最新更新