可以使用集合中唯一、可排序和不可变的任何字段来实现基于光标的分页。
_id 满足所有唯一、可排序和不可变条件。基于该字段,我们可以将最后一个文档的_id作为后续请求的光标进行排序并返回页面结果。
curl https://api.mixmax.com/items?limit=2
const items = db.items.find({}).sort({
_id: -1
}).limit(2);
const next = items[items.length - 1]._id
res.json({ items, next })
当用户想要获取第二个页面时,他们将光标(作为下一个)传递到 URL:
curl https://api.mixmax.com/items?limit=2&next=590e9abd4abbf1165862d342
const items = db.items.find({
_id: { $lt: req.query.next }
}).sort({
_id: -1
}).limit(2);
const next = items[items.length - 1]._id
res.json({ items, next })
如果我们想以不同的顺序返回结果,例如项目的日期,那么我们将在查询字符串中添加sort=launchDate。
curl https://api.mixmax.com/items?limit=2&sort=launchDate
const items = db.items.find({}).sort({
launchDate: -1
}).limit(2);
const next = items[items.length - 1].launchDate;
res.json({ items, next })
后续页面请求
curl https://api.mixmax.com/items?limit=2&sort=launchDate&next=2017-09-11T00%3A44%3A54.036Z
const items = db.items.find({
launchDate: { $lt: req.query.next }
}).sort({
_id: -1
}).limit(2);
const next = items[items.length - 1].launchDate;
res.json({ items, next });
如果我们在同一天同一时间推出了一堆商品?现在我们的 launchDate 字段不再是唯一的,并且不满足 Unique、Orderable 和 Immutable。健康)状况。我们不能将它用作游标字段。但是我们可以使用两个字段来生成游标。由于我们知道 MongoDB 中的 _id 字段总是满足上述三个条件,我们知道如果我们将它与 launchDate 字段一起使用,这两个字段的组合将满足要求,可以一起用作游标字段。
curl https://api.mixmax.com/items?limit=2&sort=launchDate
const items = db.items.find({}).sort({
launchDate: -1,
_id: -1 // secondary sort in case there are duplicate launchDate values
}).limit(2);
const lastItem = items[items.length - 1];
// The cursor is a concatenation of the two cursor fields, since both are needed to satisfy the requirements of being a cursor field
const next = `${lastItem.launchDate}_${lastItem._id}`;
res.json({ items, next });
后续页面请求
curl https://api.mixmax.com/items?limit=2&sort=launchDate&next=2017-09-11T00%3A44%3A54.036Z_590e9abd4abbf1165862d342
const [nextLaunchDate, nextId] = req.query.next.split(‘_’);
const items = db.items.find({
$or: [{
launchDate: { $lt: nextLaunchDate }
}, {
// If the launchDate is an exact match, we need a tiebreaker, so we use the _id field from the cursor.
launchDate: nextLaunchDate,
_id: { $lt: nextId }
}]
}).sort({
_id: -1
}).limit(2);
const lastItem = items[items.length - 1];
// The cursor is a concatenation of the two cursor fields, since both are needed to satisfy the requirements of being a cursor field
const next = `${lastItem.launchDate}_${lastItem._id}`;
res.json({ items, next });
参考:https://engineering.mixmax.com/blog/api-paging-built-the-right-way/