我尝试做的很简单,我在文档中一个数组;
"tags": [
{
"t" : "architecture",
"n" : 12
},
{
"t" : "contemporary",
"n" : 2
},
{
"t" : "creative",
"n" : 1
},
{
"t" : "concrete",
"n" : 3
}
]
我想将一系列项目推送到数组,如
["architecture","blabladontexist"]
如果项目存在,我想增加对象的n
值(在本例中为architecture
),
如果不是,请将其添加为新商品(价值为n=0
){ "t": "blabladontexist", "n":0}
我尝试了$addToSet
,$set
,$inc
,$upsert: true
这么多组合并且无法做到。
我们如何在MongoDB中执行此操作?
答案 0 :(得分:0)
我不相信这可以在一个命令中完成。
MongoDB不允许$ set(或$ setOnInsert)和$ inc影响单个命令中的相同字段。
您必须执行一个更新命令才能尝试$ inc字段,如果这不会更改任何文档(n = 0),请执行更新以将字段设置为默认值。
答案 1 :(得分:-1)
在MongoDB 4.2和更高版本中,更新方法现在可以获取文档或an aggregate pipeline,其中可以使用以下阶段:
$addFields
及其别名$set
$project
及其别名$unset
$replaceRoot
及其别名$replaceWith
。结合上述内容,您使用聚合管道进行的更新操作将通过过滤输入列表的过滤后的tags
数组和映射数组与输入数据中的某些数据来覆盖tags
字段。地图:
首先,用于过滤标签数组的聚合表达式使用$filter
,它的含义如下:
const myTags = ["architecture", "blabladontexist"];
{
"$filter": {
"input": "$tags",
"cond": {
"$not": [
{ "$in": ["$$this.t", myTags] }
]
}
}
}
产生过滤后的文档数组
[
{ "t" : "contemporary", "n" : 2 },
{ "t" : "creative", "n" : 1 },
{ "t" : "concrete", "n" : 3 }
]
现在,第二部分将派生将与上面串联的另一个数组。此数组需要myTags
输入数组上的$map
为
{
"$map": {
"input": myTags,
"in": {
"$cond": {
"if": { "$in": ["$$this", "$tags.t"] },
"then": {
"t": "$$this",
"n": {
"$sum": [
{
"$arrayElemAt": [
"$tags.n",
{ "$indexOfArray": [ "$tags.t", "$$this" ] }
]
},
1
]
}
},
"else": { "t": "$$this", "n": 0 }
}
}
}
}
上面的$map
本质上循环输入数组,并与每个元素比较tags
属性,检查每个元素是否在t
数组中,如果存在,则{{子文档的1}}字段变为其当前的n
值
用
n
否则将默认文档的n值添加为0。
总体而言,您的更新操作如下
您的最终更新操作将变为:
{
"$arrayElemAt": [
"$tags.n",
{ "$indexOfArray": [ "$tags.t", "$$this" ] }
]
}