MongoDB插入文档"或"增量字段(如果存在于数组中)

时间:2016-08-08 16:24:27

标签: mongodb

我尝试做的很简单,我在文档中一个数组;

"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中执行此操作?

2 个答案:

答案 0 :(得分:0)

我不相信这可以在一个命令中完成。

MongoDB不允许$ set(或$ setOnInsert)和$ inc影响单个命令中的相同字段。

您必须执行一个更新命令才能尝试$ inc字段,如果这不会更改任何文档(n = 0),请执行更新以将字段设置为默认值。

答案 1 :(得分:-1)

在MongoDB 4.2和更高版本中,更新方法现在可以获取文档或an aggregate pipeline,其中可以使用以下阶段:

  1. $addFields及其别名$set
  2. $project及其别名$unset
  3. $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" ] } 
    ] 
}