Reputation: 752
I have this mongo query to get the list of messages in a thread.
await db
.collection("threads")
.find({
_id: ObjectId(req.query.thread_id),
})
.project({
messages: {
$slice: [parseInt(req.query.offset), parseInt(req.query.limit)],
},
_id: 1,
date_created: 1,
})
.toArray();
The limit and offset is set by the client to support unlimited loading. The problem is the query gets result in the order they were added whereas it should paginate with last added messages first. How do I go about this? Is it possible that I can reverse an array before fetching or is it too much load?
This is my thread schema:
{
"_id":{
"$oid":"5f7b32c014014100176c2a55"
},
"thread_name":"personal",
"messages":[
{
"_id":{
"$oid":"5f7b32d414014100176c2a56"
},
"sender":{
"$oid":"5f7b329114014100176c2a52"
},
"type":"text",
"date_created":{
"$date":"2020-10-05T14:51:00.716Z"
},
"content":"hi"
},
{
"_id":{
"$oid":"5f7b32df14014100176c2a57"
},
"sender":{
"$oid":"5f7b329114014100176c2a52"
},
"type":"text",
"date_created":{
"$date":"2020-10-05T14:51:11.302Z"
},
"content":"hello"
},
],
"date_created":{
"$date":"2020-10-05T14:50:40.271Z"
},
}
Upvotes: 1
Views: 688
Reputation: 22276
"Is it possible that I can reverse an array before fetching?" You can't reverse what you don't have. I've seen the other answer with $reverseArray
but why spend resources reversing an array when you can just $slice the last elements?
If negative, $slice returns up to the last n elements in the array. n cannot resolve to a negative number if is specified
db.collection("threads").aggregate([
{
$match: {
_id: ObjectId(req.query.thread_id),
},
},
{
$project: {
_id: 1,
date_created: 1,
reverseMessages: {
$slice: [
"$messages",
parseInt(req.query.limit) * -1
]
}
}
}
]);
Upvotes: 1
Reputation: 185
You can use $reverseArray
option in aggregation
With aggregate
, you can use first $match
(it will replace your find
part), and then, with $project
you can add new property like reversedMessages
, where you will use $reverseArray and $slice combined
so, query should be something like this
db.collection("threads").aggregate([
{
$match: {
_id: ObjectId(req.query.thread_id),
},
},
{
$project: {
_id: 1,
date_created: 1,
reverseMessages: {
$slice: [
{ $reverseArray: "$messages" },
0,
parseInt(req.query.limit), // I guess you want to return latest n messages, where n is a limit from query
],
},
},
},
]);
Upvotes: 1