Reputation: 3245
I have a Chat
model which has a messages
array which holds Message
s. Each Message
has both a dateSent
property and a dateViewed
property. The Message
items are embedded, not referenced.
How can I sort Chat
s by most recent not viewed Message
(ie, empty dateViewed
) first and then by dateSent
? (think Facebook Messenger behavior...)
This is what I've tried so far (note that Chat
also has a users
array):
Chat.find({users._id: userId}).sort({messages.dateViewed: -1, messages.dateSent: -1}).exec(function(err, chats){
// handle err
// handle no docs found
// handle docs found
});
The above does not seem to work, as the Chat
s come out in a different order (the same as without sort()
). Any thoughts?
EDIT: The suggested answer didn't help me because I don't want to sort the Message
objects in the message
array, but rather sort the Chats
resulting from the query, by the dates in the Message
object they hold in a messages
array.
Upvotes: 0
Views: 1105
Reputation: 2699
The Aggregation pipeline should be used in order to achieve the required sort.
chats/messages:
> db.chats.find()
{ "_id" : "c1", "messages" : [ { "_id" : "m1_1", "dv" : -1, "ds" : 9000 }, { "_id" : "m1_2", "dv" : 8010, "ds" : 8000 } ] }
{ "_id" : "c2", "messages" : [ { "_id" : "m2_1", "dv" : -1, "ds" : 11000 } ] }
{ "_id" : "c3", "messages" : [ { "_id" : "m3_1", "dv" : -1, "ds" : 700 }, { "_id" : "m3_2", "dv" : 7010, "ds" : 7000 } ] }
The code to sort the data by the give criteria:
db.chats.aggregate([
{ $unwind: '$messages' },
{ $addFields: {
ts: {
$cond: [
{ $eq: ['$messages.dv', -1 ] },
'$messages.ds',
'$messages.dv']
}
}
},
{
$sort: { 'ts': -1 }
},
{
$group: {
_id: '$_id',
ts: { $max: '$ts'},
messages: { $push: '$messages' }
}
},
{
$sort: {ts: -1}
}]);
The results:
{ "_id" : "c2", "ts" : 11000, "messages" : [ { "_id" : "m2_1", "dv" : -1, "ds" : 11000 } ] }
{ "_id" : "c1", "ts" : 9000, "messages" : [ { "_id" : "m1_1", "dv" : -1, "ds" : 9000 }, { "_id" : "m1_2", "dv" : 8010, "ds" : 8000 } ] }
{ "_id" : "c3", "ts" : 7010, "messages" : [ { "_id" : "m3_2", "dv" : 7010, "ds" : 7000 }, { "_id" : "m3_1", "dv" : -1, "ds" : 700 } ] }
Upvotes: 1