I have a collection of categories, and each category has its array of _id
from a different collection.
My goal is to create an infinite scrolling by giving N records every time but from the end (the last record is always the most recent).
Category
{
"_id" : ObjectId("625167ce3859b8465ccf69dc"),
"name" : {
"en" : "Category #1"
},
"tracks" : [
ObjectId("627f8475c229513838eed070"),
ObjectId("627f84b4c229513838eed074"),
ObjectId("6280ef548b97521c1f462266"),
ObjectId("6280ef68d147e83534f4ca03"),
ObjectId("6280ef6ad147e83534f4ca07"),
ObjectId("6280ef6bd147e83534f4ca0b"),
// and so on..
]
}
Code:
categories
.aggregate([
{
$match: {
_id: ObjectId(categoryId),
},
},
{
$project: {
tracks: {
$slice: ["$tracks", -N],
},
},
},
{
$lookup: {
from: "tracks",
as: "tracks",
localField: "tracks",
foreignField: "_id",
pipeline: [{ $sort: { uploadedDate: -1 } }],
},
},
])
So basically I slice the array, to get last N elements and then look them up on tracks
collection. But I want to get N records from the end between specific range.
For example, if I have 100 records, so giving the numbers 0, 25 will return the records from 100 (total records - 0) to 75 (100 - 25 - 0).
25, 25 should return 75 to 50.
50, 25 should return 50 (total records - 50) to 25 (100 - 50 - 25).
Or maybe there is a better way, but how do I achieve it from the end?
CodePudding user response:
You can so something like:
EDIT: to support edge cases:
db.collection.aggregate([
{
$match: {_id: ObjectId("625167ce3859b8465ccf69dc")}
},
{
$addFields: {
avilableCount: {$max: [
{$subtract: [{$size: "$tracks" }, bulkSize * iterations]},
0]}
}
},
{
$project: {
tracks: {
$cond: [{$eq: ["$avilableCount", 0]},
[],
{$slice: ["$tracks", {
$max: [
{$subtract: [{$size: "$tracks"}, bulkSize * (iterations 1)]}, 0]},
{$min: [bulkSize , "$avilableCount"]}
]
}
]
}
}
}
])
This will return you a bulk of tracks with size bulkSize
, starting from the end of the list for the first iteration and going backwards along the iterations. So if you have 100 tracks with index 0-99 and the bulkSize
is 25, you will get tracks 75-99 for the first iteration, 50-74 for the 2nd iteration 25-49 for the 3rd...
The avilableCount
allows us to look at the edge cases:
In the edge case where only a part of the bulk size is available it will return this part, and if non is available it will return [].