Reputation: 35
I am build a chat app which needs to return the last message sended to every user
The document look like this:
{
username:"username",
chat:[
{
key: "long number",
messages:[
{
sender: "sender",
content:"a"
},
{
sender: "sender",
content:"b"
}
]
},
{
key: "long number",
messages:[
{
sender: "sender",
content:"1"
},
{
sender: "sender",
content:"2"
}
]
},
]
}
The result I want
[
{
key:"long number",
message:[
{
sender:"sender",
content:"b"
}
]
},
{
key:"long number",
message:[
{
sender:"sender",
content:"2"
}
]
}
]
I know how to filter the arrays using javascript array methods but it will be more efficient if i could get the messages using a single mongoose query
Upvotes: 0
Views: 30
Reputation: 1301
https://mongoplayground.net/p/qcBkxntBDbX
db.collection.aggregate([
// Note you'll probably want a "$match" here to match on the specific document
// Unwind on chat to access the messages array for each field
{
"$unwind": "$chat"
},
// Get the last item from the messages array for each chat
{
"$addFields": {
"message": {
"$arrayElemAt": [
"$chat.messages",
-1
]
}
}
},
// Regroup by key
{
"$group": {
"_id": "$chat.key",
"message": {
$addToSet: "$message"
}
}
},
// Rename grouped _id back to "key", remove the _id, and carry forward the message
{
"$project": {
"key": "$_id",
"message": 1,
"_id": 0
}
}
])
This matches the requirements as you wrote them, but you may want to include the documents _id or something based on your use case. Wouldn't be too tricky to carry that forward in the group stage though.
Upvotes: 1