首页 > 解决方案 > 如何用猫鼬跳过_id?

问题描述

mongoose的问题.skip(num)在于,在向集合中添加数据时,skip(num)可能会返回先前搜索中存在的数据。解决方案将从 _id 中跳过,但我找不到这样的选项。

所以而不是:

db.collection.find().sort({ _id: -1 }).skip(num).limit(50);

我希望能够:

db.collection.find().sort({ _id: -1 }).skip(_id).limit(50);

或者,如果我能得到它的索引_id也应该没问题:

let res = await db.collection.findOne({_id});
let {index} = res;
db.collection.find().sort({ _id: -1 }).skip(index).limit(50);

我使用 Caffeinated.tech 的方法并尝试过:

const list = async function({
  end_cursor = ''
} = {}) {
  return await db.discovery.where('_id').gt(end_cursor).sort({ _id: -1 }).limit(50);
}

我得到了

CastError: Cast to ObjectId failed for value "" at path "_id" for model "discovery"

正确答案是

const list = async function(end_cursor) {
  if (!end_cursor) {
    return await db.discovery.where('_id').sort({ _id: -1 }).limit(50);
  }
  return await db.discovery.where('_id').lt(end_cursor).sort({ _id: -1 }).limit(50);
}

标签: mongoose

解决方案


如果您想在对查询进行分页时避免重复,我建议您在查询中使用gtand而不是使用and 。这还具有为您提供恒定速度的好处,即使您在页面下方有数千个文档(随着值越大,查询越慢)。ltwhereskiplimitskip

这是一般的想法:

我正在通讯录中列出联系人。我已经加载并显示了前 100 个联系人,按createdAt日期升序排序并搜索名称aero

  1. 从您的 UI / API / 发送当前显示的最后一个联系人的 id 以及当前的排序/搜索参数。

  2. 从数据库加载所述联系人。例如它是name: "aero 100"和`createdAt:“01/01/2019”

  3. 现在使用此联系人构建您的查询,以便您在此联系人之后继续下一个联系人。因此,您将要搜索相同的姓名,并且由于我们按创建的排序方式添加此排序顺序搜索createdAt 大于最后一个联系人createdAt时间戳的联系人。

 let lastContact = await Contact.findById(lastId)
 let nextPage = await Contact
   .where({ name: /aero/i })
   .sort({createdAt: 1})
   .gt(createdAt, lastContact.createdAt)
   .limit(100)
   .exec()

我已经发布了一个用于 mongoose 的插件,除非您需要执行一些复杂的查询/填充等,否则它应该会更容易:mongoose-fast-pagination


推荐阅读