在mongodb中实现分页

     2023-03-10     33

关键词:

【中文标题】在mongodb中实现分页【英文标题】:Implementing pagination in mongodb 【发布时间】:2015-03-22 04:52:34 【问题描述】:

我知道使用skip 来实现分页是一种不好的做法,因为当您的数据变大时skip 开始消耗大量内存。解决此问题的一种方法是使用自然顺序 by _id 字段:

//Page 1
db.users.find().limit(pageSize);
//Find the id of the last document in this page
last_id = ...

//Page 2
users = db.users.find('_id'> last_id). limit(10);

问题是 - 我是 mongo 的新手,不知道获得这个的最佳方法是什么last_id

【问题讨论】:

docs.mongodb.org/manual/reference/operator/query/gt 谢谢!但我看不出我应该如何获得last_id。我应该使用什么代码来代替那些点:last_id = ...? 【参考方案1】:

您所说的概念可以称为“转发分页”。一个很好的理由与使用 .skip().limit() 修饰符不同,这不能用于“返回”到前一页或确实“跳过”到特定页面。至少不需要花费大量精力来存储“看到”或“发现”页面,所以如果你想要那种类型的“页面链接”分页,那么你最好坚持使用 .skip() 和 @987654325 @ 方法,尽管存在性能缺陷。

如果只“向前”对您来说是一个可行的选择,那么基本概念如下:

db.junk.find().limit(3)

 "_id" : ObjectId("54c03f0c2f63310180151877"), "a" : 1, "b" : 1 
 "_id" : ObjectId("54c03f0c2f63310180151878"), "a" : 4, "b" : 4 
 "_id" : ObjectId("54c03f0c2f63310180151879"), "a" : 10, "b" : 10 

当然,这是您的第一页,限制为 3 项。现在考虑一下迭代光标的代码:

var lastSeen = null;
var cursor = db.junk.find().limit(3);

while (cursor.hasNext()) 
   var doc = cursor.next();
   printjson(doc);
   if (!cursor.hasNext())
     lastSeen = doc._id;

这样迭代光标并执行某些操作,当确实到达光标中的最后一项时,您将lastSeen 值存储到当前_id

ObjectId("54c03f0c2f63310180151879")

在您随后的迭代中,您只需将您保留(在会话中或其他任何地方)的 _id 值提供给查询:

var cursor = db.junk.find( "_id":  "$gt": lastSeen  ).limit(3);

while (cursor.hasNext()) 
   var doc = cursor.next();
   printjson(doc);
   if (!cursor.hasNext())
     lastSeen = doc._id;


 "_id" : ObjectId("54c03f0c2f6331018015187a"), "a" : 1, "b" : 1 
 "_id" : ObjectId("54c03f0c2f6331018015187b"), "a" : 6, "b" : 6 
 "_id" : ObjectId("54c03f0c2f6331018015187c"), "a" : 7, "b" : 7 

并且这个过程一遍又一遍地重复,直到无法获得更多结果。

这是_id 等自然秩序的基本过程。对于其他事情,它会变得更复杂一些。考虑以下几点:

 "_id": 4, "rank": 3 
 "_id": 8, "rank": 3 
 "_id": 1, "rank": 3     
 "_id": 3, "rank": 2 

要将其分成按排名排序的两个页面,那么您基本上需要知道的是您“已经看到”的内容并排除这些结果。所以看第一页:

var lastSeen = null;
var seenIds = [];
var cursor = db.junk.find().sort( "rank": -1 ).limit(2);

while (cursor.hasNext()) 
   var doc = cursor.next();
   printjson(doc);
   if ( lastSeen != null && doc.rank != lastSeen )
       seenIds = [];
   seenIds.push(doc._id);
   if (!cursor.hasNext() || lastSeen == null)
     lastSeen = doc.rank;


 "_id": 4, "rank": 3 
 "_id": 8, "rank": 3 

在下一次迭代中,您希望小于或等于 lastSeen“排名”分数,但也排除那些已经看过的文档。您可以使用 $nin 运算符来执行此操作:

var cursor = db.junk.find(
     "_id":  "$nin": seenIds , "rank": "$lte": lastSeen 
).sort( "rank": -1 ).limit(2);

while (cursor.hasNext()) 
   var doc = cursor.next();
   printjson(doc);
   if ( lastSeen != null && doc.rank != lastSeen )
       seenIds = [];
   seenIds.push(doc._id);
   if (!cursor.hasNext() || lastSeen == null)
     lastSeen = doc.rank;


 "_id": 1, "rank": 3     
 "_id": 3, "rank": 2 

您实际持有多少“seenId”取决于您的结果在该值可能发生变化的地方有多“精细”。在这种情况下,您可以检查当前的“排名”分数是否不等于 lastSeen 值并丢弃当前的 seenIds 内容,使其不会增长太多。

这就是“转发分页”的基本概念,供大家练习和学习。

【讨论】:

@Neil-Lunn,这样一个完整而精彩的解释。我发现了一些关于你的事情,你似乎从不睡觉,我监视你(开玩笑),看到你总是 24/7 在线;) @Disposer 移动应用程序和机器人。机器的崛起。【参考方案2】:

在MongoDB中实现分页的最简单方法

  // Pagination
  const page = parseInt(req.query.page, 10) || 1;
  const limit = parseInt(req.query.limit, 10) || 25;
  const startIndex = (page - 1) * limit;
  const endIndex = page * limit;
  query = query.skip(startIndex).limit(limit);

【讨论】:

这种方法有它的缺点。它必须跳过前 n 个元素,这意味着它必须读取前 n 个元素,这会降低性能

如何在nodejs + postgresql中实现分页

】如何在nodejs+postgresql中实现分页【英文标题】:Howtoimplementpaginationinnodejs+postgresql【发布时间】:2018-06-2604:23:58【问题描述】:我是Node.js的新手。我想在Node.js中使用express作为框架和Postgresql作为数据库在我的Api编写中实现分页... 查看详情

如何在排名查询中实现分页?

】如何在排名查询中实现分页?【英文标题】:Howtoimplementpaginginrankingquery?【发布时间】:2014-03-0506:18:32【问题描述】:我正在尝试使用MySQL进行排名。我找到了一篇关于它的好文章,没有使用自连接(rankingwithoutselfjoin)。SELECTscore... 查看详情

如何在 dojox.datagrid 中实现分页

】如何在dojox.datagrid中实现分页【英文标题】:howtoimplementpaginationindojox.datagrid【发布时间】:2019-02-1319:37:34【问题描述】:我有一个在dojox.datagrid中显示分页的请求,我尝试搜索但没有运气。想知道dojox.datagrid中是否可以分页,... 查看详情

java示例代码_在Spring MVC 3中实现分页

java示例代码_在Spring MVC 3中实现分页 查看详情

如何在 React 中实现分页

】如何在React中实现分页【英文标题】:HowtoimplementpaginationinReact【发布时间】:2017-03-0701:58:48【问题描述】:我是ReactJS的新手,正在其中创建一个简单的TODO应用程序。实际上,它是一个非常基本的应用程序,没有数据库连接,... 查看详情

如何在Android listview中实现分页

】如何在Androidlistview中实现分页【英文标题】:HowtoimplementpaginationinAndroidlistview【发布时间】:2013-05-1517:28:04【问题描述】:我正在为Android应用程序工作,我需要在其中显示带有项目的列表视图。但是列表视图中要显示更多元素... 查看详情

如何在 Git 标签中实现分页

】如何在Git标签中实现分页【英文标题】:HowtoachievepaginationinGittag【发布时间】:2021-11-0519:04:31【问题描述】:谁帮帮我将git标签限制为100需要在第一次获取时获取前100个标签需要传递一些key或token来获取下一批可以像分页一样... 查看详情

使用 scrollViewDidScroll 方法在 UITableView 中实现分页?

】使用scrollViewDidScroll方法在UITableView中实现分页?【英文标题】:ImplementingpaginationinUITableViewwithscrollViewDidScrollmethod?【发布时间】:2014-09-1714:59:06【问题描述】:我正在构建一个文章阅读应用程序。我正在使用AFNetworking第三方库... 查看详情

如何在 PHP 中实现分页? [关闭]

】如何在PHP中实现分页?[关闭]【英文标题】:HowdoyouimplementpaginationinPHP?[closed]【发布时间】:2010-09-2100:57:37【问题描述】:PHP中通常如何实现分页结果?我想要一个包含10个结果的结果页面。在导航中向前翻页会给我下一组和上... 查看详情

如何在 Spring MVC 3 中实现分页 [关闭]

】如何在SpringMVC3中实现分页[关闭]【英文标题】:HowtoimplementpaginationinSpringMVC3[closed]【发布时间】:2011-01-1517:54:46【问题描述】:是否有任何开箱即用、易于实现的标准分页组件/标签库或代码示例可用于SpringMVC中的分页?【问题... 查看详情

如何使用hibernate在spring boot中实现分页

】如何使用hibernate在springboot中实现分页【英文标题】:Howtoimplementpaginationinspringbootwithhibernate【发布时间】:2015-12-0217:41:44【问题描述】:我正在使用带有休眠功能的SpringBoot,并且我想在我的项目中使用分页。我在谷歌上搜索并... 查看详情

如何在 SQL for MS Access 中实现分页?

】如何在SQLforMSAccess中实现分页?【英文标题】:HowdoIimplementpaginationinSQLforMSAccess?【发布时间】:2009-12-1412:25:24【问题描述】:我正在使用ASP.NET通过OdbcConnection类访问MicrosoftAccess2002数据库(MDB),虽然速度很慢,但它运行良好。我... 查看详情

在 ASP.NET Core 2.1 Web API 中实现分页

】在ASP.NETCore2.1WebAPI中实现分页【英文标题】:ImplementPaginationinASP.NETCore2.1WebAPI【发布时间】:2019-02-1905:28:50【问题描述】:我搜索了,但并没有真正找到关于如何在ASP.NETWebAPICore2.1应用程序中实现分页逻辑的文章...我有以下[Route... 查看详情

如何在 SQL for MS Access 中实现分页?

】如何在SQLforMSAccess中实现分页?【英文标题】:HowdoIimplementpaginationinSQLforMSAccess?【发布时间】:2009-12-1412:25:24【问题描述】:我正在使用ASP.NET通过OdbcConnection类访问MicrosoftAccess2002数据库(MDB),虽然速度很慢,但它运行良好。我... 查看详情

如何在后端自定义查询中实现分页

】如何在后端自定义查询中实现分页【英文标题】:Howtoimplementpaginationincustomqueryinbackand【发布时间】:2016-02-2319:31:05【问题描述】:我想在我的自定义查询中实现分页,就像在提供的查询中一样。我想提供行数和页数。我尝试... 查看详情

在ssh项目中实现分页效果

在实现分页的时候,我使用的是数据库下面的User表,实现的效果是通过分页查询能够将表中的数据分页显示,点击相关的按钮实现:首页、上一页、下一页、末页的显示1新建一个dynamicwebproject项目,导入SSH项目所需要的jarantlr-2.... 查看详情

用servlet与jsp中实现分页查询

这个题目,总共分4个部分1.查询总页数,把页码显示在页面上2.把每页的内容显示在页面上3.首页,尾页,上一页,下一页4.下拉列表中的页数,(根据页数变动,选中第几页提交到第几页)详解如下:(一部分代码在servlet中,... 查看详情

在存储库级别在 Doctrine2 ORM 中实现分页的最佳实践

】在存储库级别在Doctrine2ORM中实现分页的最佳实践【英文标题】:BestpracticesofimplementingpaginationinDoctrine2ORMonrepositorylevel【发布时间】:2013-08-1909:03:07【问题描述】:我知道Doctrine\'sPaginator,但它适用于DQL级别。我正在寻找的是一... 查看详情