【问题标题】:How to implement twitter and facebook api like cursor based pagination in mongodb in nodejs using official mongodb client?如何使用官方 mongodb 客户端在 nodejs 中的 mongodb 中实现 twitter 和 facebook api 之类的基于光标的分页?
【发布时间】:2020-02-12 04:35:16
【问题描述】:

我正在尝试实现pagination,它不应该在数据插入或删除的不同页面中显示重复数据。

使用skiplimit 对数据进行分页的基本offset-based 方法在此给出
How to implement pagination for mongodb in node.js using official mongodb client?

基于偏移量的方法有一个很大的缺陷:如果结果列表在调用 API 之间发生了变化,则索引会发生变化并导致项目被返回两次或被跳过并且永远不会返回

此问题已在
https://www.sitepoint.com/paginating-real-time-data-cursor-based-pagination/

进行了演示

基于时间的分页方法会好一点,因为不再跳过结果。如果您查询第一页,然后删除了一个新项目,它不会改变您第二页中的结果,一切都很好。但是,这种方法有一个重大缺陷:如果同时创建了多个项目怎么办?

基于偏移量和基于时间的方法并不是那么完美。所以我需要 twitter 和 facebook api 的工作方式,它使用基于光标的方法,使用 nodejs 和 official mongodb client?

【问题讨论】:

  • 使用 ObjectId 进行分页。它是独一无二的,并且是基于时间的。

标签: node.js mongodb express pagination real-time


【解决方案1】:

可以使用集合中唯一、可排序和不可变的任何字段来实现基于光标的分页。

_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=launchDatecurl 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/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 2015-07-06
    • 2017-08-16
    • 2020-01-04
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多