Как правильно обновить элемент в массиве с помощью Mongoose - PullRequest
1 голос
/ 07 февраля 2020

Я прочитал как можно больше статей о том, как правильно обновить элемент в массиве в MongoDB (например: Пн goose, обновить значения в массиве объектов ), и подумал, что следовал всем советам, но я все еще ошибаюсь, и был бы очень признателен, если бы кто-то мог обнаружить мою ошибку, поскольку я пытался отлаживать ее часами!

Проблема, которую я В частности, я имею в виду, что вызов findOneAndUpdate, по-видимому, просто обновляет первый элемент в массиве «itineraryItems», независимо от того, соответствует ли он моему запросу для указанного элемента c или нет.

Данные в моем пользовательская коллекция (2 элемента массива в массиве itineraryItems пользовательского документа):

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 (т.е. я передаю известный идентификатор для элемента в массиве) вроде бы нормально работает. Это два других случая, которые кажутся неудачными.

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;
}

Мой понедельник goose вызов 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();
                    }     
                }
            );

Большое спасибо, если вы можете сказать мне, что я делаю неправильно!

1 Ответ

1 голос
/ 07 февраля 2020

Вы должны соответствовать вашему subdocument, используя $elemMatch, если вы хотите обновить только subdocument, который соответствует всем условиям

Как это,

{
    _id: user._id,
    'itineraryItems':{
        $elemMatch:{
            iType: type,
            startDate: startDate,
            endDate: endDate,
            includeTravelTime: includeTravelTime,
            travelTimeMinutes: travelTimeMinutes,
            item: mongoose.Types.ObjectId(itemId)
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...