I have read as many articles as I can on how to correctly update an element in an array in a MongoDB (such as this one: Mongoose, update values in array of objects), and thought I had followed all the advice, but I am still getting this wrong, and would be very grateful if someone could spot my error, as I've been trying to debug this for hours!
The problem I am specifically having is that the findOneAndUpdate call seems to be just updating the first element in the array of "itineraryItems", no matter whether it matches my query for a specific element or not.
Data in my user collection (2 array elements in the itineraryItems array on the user document):
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
}
]
}
My query building function: Note that queries that satisfy the first if statement (i.e. I pass in a known id for the element in the array) seem to work fine. It is the other 2 cases that seem to fail.
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;
}
My Mongoose call to 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();
}
}
);
Thanks a lot if you can tell me what I am doing wrong!