如何使用官方 mongodb 客户端在 node.js 中为 mongodb 实现分页? [英] How to implement pagination for mongodb in node.js using official mongodb client?

查看:15
本文介绍了如何使用官方 mongodb 客户端在 node.js 中为 mongodb 实现分页?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为 mongodb 实现分页en.wikipedia.org/wiki/Node.js" rel="nofollow noreferrer">node.js 环境使用 官方 mongodb 包.我试图在互联网上找到,但都是基于 猫鼬 的链接.我不想使用猫鼬.

I want to implement pagination for mongodb in node.js enviroment using offical mongodb package. I tried to find out on internet but all are mongoose based links. I dont want to use mongoose.

如何使用
提供的官方客户端 api 实现分页http://mongodb.github.io/node-mongodb-native/3.1/api/

推荐答案

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

Offset-based approach has a big flaw: if the results list has changed between calls to the API, the indices would shift and cause an item to be either returned twice or skipped and never returned

这个问题在https://www.sitepoint.com/paginating-real-基于时间数据光标的分页/

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

Time-based pagination approach would be little better because results are no longer skipped. If you query the first page, and then a new item is deleted, it won’t shift the results in your second page and all is fine. However, this approach has a major flaw: what if there is more than one item that was created at the same time?

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

Best would be to use Cursor based pagination
Which can be implemented using any field in collection which is Unique, Orderable and Immutable.

_id 满足所有唯一、可排序和不可变条件.基于这个字段,我们可以对页面结果进行排序并返回,以最后一个文档的_id作为后续请求的光标.

_id satisfy all Unique, Orderable and Immutable conditions. Based on this field we can sort and return page result with _id of last document as the cusror for subsequent request.

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

when the user wants to get the second page, they pass the cursor (as next) on the 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

If we want to return results in a different order, such as the date the item then we will add sort=launchDate to the querystring. 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

If we launched a bunch of items on the same day and time? Now our launchDate field is no longer unique and doesn’t satisfy Unique, Orderable and Immutable. condition. We can’t use it as a cursor field. But we could use two fields to generate the cursor.Since we know that the _id field in MongoDB always satisfies the above three condition, we know that if we use it alongside our launchDate field, the combination of the two fields would satisfy the requirements and could be together used as a cursor field. 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/

这篇关于如何使用官方 mongodb 客户端在 node.js 中为 mongodb 实现分页?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆