MongoDb - Return 来自嵌套数组末尾的 N 个元素的批量在每次调用时向后循环(分页)
MongoDb - Return bulks of N elements from the end of a nested array looping backwards at each call (pagination)
我有一个类别集合,每个类别都有来自不同集合的 _id
数组。
我的目标是通过每次提供 N 条记录但从最后开始(最后一条记录总是最新的)来创建无限滚动。
类别
{
"_id" : ObjectId("625167ce3859b8465ccf69dc"),
"name" : {
"en" : "Category #1"
},
"tracks" : [
ObjectId("627f8475c229513838eed070"),
ObjectId("627f84b4c229513838eed074"),
ObjectId("6280ef548b97521c1f462266"),
ObjectId("6280ef68d147e83534f4ca03"),
ObjectId("6280ef6ad147e83534f4ca07"),
ObjectId("6280ef6bd147e83534f4ca0b"),
// and so on..
]
}
代码:
categories
.aggregate([
{
$match: {
_id: ObjectId(categoryId),
},
},
{
$project: {
tracks: {
$slice: ["$tracks", -N],
},
},
},
{
$lookup: {
from: "tracks",
as: "tracks",
localField: "tracks",
foreignField: "_id",
pipeline: [{ $sort: { uploadedDate: -1 } }],
},
},
])
所以基本上我对数组进行切片,以获取最后 N 个元素,然后在 tracks
集合中查找它们。但我想从特定范围之间的末尾获取 N 条记录。
例如,如果我有 100 条记录,那么给定迭代次数 0 和批量大小:25,将返回最后 25 个元素(索引 75-99)。
在迭代 1 中,将返回下一个(向后移动)25 个元素(索引 50-74),依此类推...
你可以这样:
编辑: 支持边缘情况:
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"]}
]
}
]
}
}
}
])
这将为您 return 提供大量大小为 bulkSize
的曲目,从第一次迭代的列表末尾开始,并沿着迭代向后移动。因此,如果您有 100 条索引为 0-99 且 bulkSize
为 25 的曲目,则第一次迭代将获得曲目 75-99,第二次迭代将获得曲目 50-74,第三次迭代将获得曲目 25-49...
avilableCount
允许我们查看边缘情况:
在只有一部分批量大小可用的边缘情况下,它将 return 这部分,如果不可用,它将 return [].
我有一个类别集合,每个类别都有来自不同集合的 _id
数组。
我的目标是通过每次提供 N 条记录但从最后开始(最后一条记录总是最新的)来创建无限滚动。
类别
{
"_id" : ObjectId("625167ce3859b8465ccf69dc"),
"name" : {
"en" : "Category #1"
},
"tracks" : [
ObjectId("627f8475c229513838eed070"),
ObjectId("627f84b4c229513838eed074"),
ObjectId("6280ef548b97521c1f462266"),
ObjectId("6280ef68d147e83534f4ca03"),
ObjectId("6280ef6ad147e83534f4ca07"),
ObjectId("6280ef6bd147e83534f4ca0b"),
// and so on..
]
}
代码:
categories
.aggregate([
{
$match: {
_id: ObjectId(categoryId),
},
},
{
$project: {
tracks: {
$slice: ["$tracks", -N],
},
},
},
{
$lookup: {
from: "tracks",
as: "tracks",
localField: "tracks",
foreignField: "_id",
pipeline: [{ $sort: { uploadedDate: -1 } }],
},
},
])
所以基本上我对数组进行切片,以获取最后 N 个元素,然后在 tracks
集合中查找它们。但我想从特定范围之间的末尾获取 N 条记录。
例如,如果我有 100 条记录,那么给定迭代次数 0 和批量大小:25,将返回最后 25 个元素(索引 75-99)。
在迭代 1 中,将返回下一个(向后移动)25 个元素(索引 50-74),依此类推...
你可以这样:
编辑: 支持边缘情况:
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"]}
]
}
]
}
}
}
])
这将为您 return 提供大量大小为 bulkSize
的曲目,从第一次迭代的列表末尾开始,并沿着迭代向后移动。因此,如果您有 100 条索引为 0-99 且 bulkSize
为 25 的曲目,则第一次迭代将获得曲目 75-99,第二次迭代将获得曲目 50-74,第三次迭代将获得曲目 25-49...
avilableCount
允许我们查看边缘情况:
在只有一部分批量大小可用的边缘情况下,它将 return 这部分,如果不可用,它将 return [].