I'm working on message system and I need to get last message from each user who sent message to logged user. I have this structure in mongoDB:
[{
"_id": "551bd621bb5895e4109bc3ce",
"from": "admin",
"to": "user1",
"message": "message1",
"created": "2015-04-01T11:27:29.671Z"
}, {
"_id": "551bd9acf26208ac1d9b831d",
"from": "user1",
"to": "admin",
"message": "message2",
"created": "2015-04-01T11:42:36.936Z"
}, {
"_id": "551bdd6d849d53001dd8a64a",
"from": "user1",
"to": "user2",
"message": "message3",
"created": "2015-04-01T11:58:37.858Z"
}, {
"_id": "551bdd99849d53001dd8a64b",
"from": "user2",
"to": "admin",
"__v": 0,
"message": "message4",
"created": "2015-04-01T11:59:21.005Z"
}, {
"_id": "551bdda1849d53001dd8a64c",
"from": "user1",
"to": "admin",
"__v": 0,
"message": "message5",
"created": "2015-04-01T11:59:29.971Z"
}]
I need to get fields from
, message
and created
from last message of each user who sent message to logged user. I tried use distinct but it returns only one field. I have this:
Message.find({
to: req.user.username
})
.select('message created')
.sort('-created')
.exec(function (err, messages) {
if (err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
res.json(messages)
}
});
but it returns all users who sent messages to logged user and I need to have only unique users and their last message. Is there some way how to do it with mongoose?
Use aggregation framework where your pipeline stages have $match
, $sort
, $group
and $project
expressions:
Message.aggregate(
[
// Matching pipeline, similar to find
{
"$match": {
"to": req.user.username
}
},
// Sorting pipeline
{
"$sort": {
"created": -1
}
},
// Grouping pipeline
{
"$group": {
"_id": "$from",
"message": {
"$first": "$message"
},
"created": {
"$first": "$created"
}
}
},
// Project pipeline, similar to select
{
"$project": {
"_id": 0,
"from": "$_id",
"message": 1,
"created": 1
}
}
],
function(err, messages) {
// Result is an array of documents
if (err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
res.json(messages)
}
}
);
If req.user.username = "admin"
, with your sample collection then the result is:
{
"result" : [
{
"message" : "message4",
"created" : "2015-04-01T11:59:21.005Z",
"from" : "user2"
},
{
"message" : "message5",
"created" : "2015-04-01T11:59:29.971Z",
"from" : "user1"
}
],
"ok" : 1
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With