【问题标题】:How to correctly update an element in an array using Mongoose如何使用 Mongoose 正确更新数组中的元素
【发布时间】:2020-05-23 14:43:42
【问题描述】:

我已经阅读了尽可能多的关于如何正确更新 MongoDB 中数组中的元素的文章(例如这篇文章:Mongoose, update values in array of objects),并认为我已经遵循了所有建议,但我仍然得到这个错误,如果有人能发现我的错误,将不胜感激,因为我已经尝试调试了好几个小时!

我特别遇到的问题是 findOneAndUpdate 调用似乎只是更新“itineraryItems”数组中的第一个元素,无论它是否匹配我对特定元素的查询。

我的用户集合中的数据(用户文档上的 itineraryItems 数组中的 2 个数组元素):

db.users.find({_id: ObjectId("5dd65ce7998d626a2c71a547"), {itineraryItems: 1})

{ "_id" : ObjectId("5dd65ce7998d626a2c71a547"), 
  "itineraryItems" : [ 
     { "_id" : ObjectId("5e3d5a301b65f3f9fd1621f8"), 
       "iType" : "event", 
       "startDate" : ISODate("2020-02-07T11:00:00Z"), 
       "endDate" : ISODate("2020-02-07T13:00:00Z"), 
       "includeTravelTime" : false, 
       "travelTimeMinutes" : 0, 
       "item" : null, 
       "event" : ObjectId("5dea66c182d9ac6fb4c6f36e") 
     }, 
     { "_id" : ObjectId("5e3d5a341b65f3f9fd1621ff"), 
       "iType" : "item", 
       "startDate" : ISODate("2020-02-07T11:00:00Z"), 
       "endDate" : ISODate("2020-02-07T13:00:00Z"), 
       "includeTravelTime" : false, 
       "travelTimeMinutes" : 0, 
       "item" : ObjectId("5e29df801f026697b71f7f48"), 
       "event" : null 
     } 
  ] 
}

我的查询构建功能: 请注意,满足第一个 if 语句的查询(即我为数组中的元素传入一个已知的 id)似乎工作正常。其他 2 个案例似乎失败了。

function getUpdateItineraryElementQuery(user, id, type, startDate, endDate, includeTravelTime, travelTimeMinutes, itemId) {
    let query = {};
    if (
        (id!=null) && 
        (id!='not_set')
    ) {
        query = {
            _id:                    user._id,
            'itineraryItems._id':   mongoose.Types.ObjectId(id)
        };
    } else {

        if (type==='event') {
            query = {
                _id:                                    user._id,
                'itineraryItems.iType':                 type,
                'itineraryItems.startDate':             startDate,
                'itineraryItems.endDate':               endDate,
                'itineraryItems.includeTravelTime':     includeTravelTime,
                'itineraryItems.travelTimeMinutes':     travelTimeMinutes,
                'itineraryItems.event':                 mongoose.Types.ObjectId(itemId)
            };
        } else {
            if (type==='item') {
                query = {
                    _id:                                    user._id,
                    'itineraryItems.iType':                 type,
                    'itineraryItems.startDate':             startDate,
                    'itineraryItems.endDate':               endDate,
                    'itineraryItems.includeTravelTime':     includeTravelTime,
                    'itineraryItems.travelTimeMinutes':     travelTimeMinutes,
                    'itineraryItems.item':                  mongoose.Types.ObjectId(itemId)
                };
            }
        }
    }
    return query;
}

我的 Mongoose 调用 findOneAndUpdate:

 User.findOneAndUpdate(
                query,
                {
                    'itineraryItems.$.startDate':           dtNewStartDate,
                    'itineraryItems.$.endDate':             dtNewEndDate,
                    'itineraryItems.$.includeTravelTime':   newIncludeTravelTime,
                    'itineraryItems.$.travelTimeMinutes':   newTravelTimeMinutes
                // eslint-disable-next-line no-unused-vars
                }, (err, doc) => {
                    if (err) {
                        // not found?
                        res.sendStatus(404).end();
                    } else {
                        // ok
                        res.sendStatus(200).end();
                    }     
                }
            );

如果你能告诉我我做错了什么,非常感谢!

【问题讨论】:

  • 如果你想更新数组中的 all 元素,那么语法应该是 itineraryItems.$[].startDate 而不是 itineraryItems.$.startDate
  • 谢谢温弗里德。我不打算这样做,但很高兴知道这种语法 - 非常感谢!

标签: arrays mongodb mongoose


【解决方案1】:

如果您只想更新匹配所有条件

subdocument,则需要使用$elemMatch 匹配您的subdocument

这样,

{
    _id: user._id,
    'itineraryItems':{
        $elemMatch:{
            iType: type,
            startDate: startDate,
            endDate: endDate,
            includeTravelTime: includeTravelTime,
            travelTimeMinutes: travelTimeMinutes,
            item: mongoose.Types.ObjectId(itemId)
        }
    }
}

【讨论】:

  • 谢谢!我刚刚修改了我的代码并且它正在工作。非常感谢!
猜你喜欢
  • 2014-01-31
  • 2016-01-20
  • 1970-01-01
  • 2020-04-18
  • 2017-04-04
  • 2018-12-14
  • 2018-07-12
  • 1970-01-01
  • 2017-12-05
相关资源
最近更新 更多