I have a MongoDB collection for storing chat objects with messages embedded as a nested array. The entire collection looks like this:
chats = [
{
_id: 0,
messages: [
{
_id: 0,
text: 'First message'
},
{
_id: 1,
text: 'Second message'
}
]
},
{
_id: 1,
messages: []
}
]
I would like to update a single message and return it to the user. I can update the message like this (in Node):
const chat = chats.findOneAndUpdate({
_id: ObjectId(chatID),
"messages._id": ObjectId(messageID)
}, {
$set: {
"messages.$.text": newText
}
});
The issue is that this query updates a message and returns a chat object, meaning that I have to look for an updated message in my code again. (ie chat.messages.find(message => message._id === messageID)
).
Is there a way to get a message object from MongoDB directly? It would also be nice to do the update in the same query.
EDIT: I am using Node with mongodb.
Thank you!
Since MongoDB methods findOneAndUpdate
, findAndModify
do not allow to get the updated document from array field,
$
after array field namereturnNewDocument: true
will return updated(new) document but this will return whole document object The problem is, MongoDB cannot allowing to use a positional projection and return the new document together
For temporary solution try using projection , this will return original document from array field using $
positional,
const chat = chats.findOneAndUpdate(
{
_id: ObjectId(chatID),
"messages._id": ObjectId(messageID)
},
{ $set: { "messages.$.text": newText } },
{
projection: { "messages.$": 1 }
}
);
Result:
{
"_id" : 0.0,
"messages" : [
{
"_id" : 0.0,
"text" : "Original Message"
}
]
}
To get an updated document, a new query could be made like this:
const message = chats.findOne({
_id: ObjectId(chatID),
"messages._id": ObjectId(messageID)
}, {
projection: {'messages.$': 1},
}).messages[0];
Result:
{
"_id": 0.0,
"text": "New message",
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.