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

问题描述 投票:0回答:1

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

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

emotes只能包含1个userId实例。在推送一个新的表情元素之前,我需要检查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移动到一个新的集合或改变它的结构,如果这让事情变得更容易。我不能改变其他任何东西。

node.js mongodb
1个回答
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表达式内,则可以使用位置运算符更新此字段。

© www.soinside.com 2019 - 2024. All rights reserved.