Mongodb有条件地更新双重嵌套数组

时间:2017-12-17 02:45:03

标签: node.js mongodb

我的收藏品看起来像这样。文档包含suggestions数组。每个建议都可以有一个emotes数组。用户每个建议只能表现一次。请注意,文档可以有多个建议

{
    id: 1,
    suggestions:[
        {
            id: 463,
            emotes:[
                {
                    id: 35,
                    userId: 2
                },
                {
                    id: 23,
                    userId: 3
                },
            ]
        },
        ...
    ]
},
...

emotes只能包含userId的1个实例。在推送新的表情元素之前,我需要检查userId中是否存在emotes

我尝试过的解决方案:

(我使用更新命令语法来访问MongoDB 3.6功能。)

首次尝试:  addToSet无效,因为emote数组元素由userId键入,而不是整个对象。

db.get().command({
    update: 'channels',
    updates:[
        {
            q:{ 
                channelId, 
                  "suggestions.id": suggestionOid,
            },
            u:{
                $addToSet:
                {
                    "suggestions.$[s].emotes": data
                }
            },
            arrayFilters:[
                { 's.id': suggestionOid }
            ]
        }
    ]
})

第二次尝试: 以下不起作用。用户可能已经有另一个建议的表情,这将导致$ne查询条件失败。这意味着用户每个文档只能表示一个建议,他们应该能够表达对文档的所有建议。

db.get().command({
    update: 'channels',
    updates:[
        {
            q:{ 
                channelId, 
                  'suggestions.emotes.userId': {$ne: userId },
                  "suggestions.id": suggestionOid,
            },
            u:{
                $push:
                {
                    "suggestions.$[s].emotes": data
                }
            },
            arrayFilters:[
                { 's.id': suggestionOid }
            ]
        }
    ]
})

我愿意将emotes移动到新的集合或更改其结构,如果这样可以使事情变得更容易。我无法改变其他任何事情。

1 个答案:

答案 0 :(得分:0)

我使用$elemMatch运算符解决了这个问题。

return channels.updateOne(
    {
        channelId, 
        "suggestions":{
            $elemMatch:{
                id: suggestionOid,
                'emotes.user': {$ne: user }
            }
        },
    },
    {
        $push:
        {
            "suggestions.$.emotes": data
        }
    }
)

来自mongodb docs的重要部分 https://docs.mongodb.com/manual/reference/operator/update/positional/

  

如果查询使用否定运算符(例如$ ne)匹配数组,   $ not或$ nin,那么你不能使用位置运算符来更新   这个数组的值。

     

但是,如果查询的否定部分位于   $ elemMatch表达式,然后你可以使用位置运算符来   更新此字段。