我知道使用这种方法来skip
实现分页是一种不好的做法,因为当数据变大skip
时,这会消耗大量内存。解决此问题的一种方法是按_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
您正在谈论的概念可以称为“转发分页”。这有一个很好的理由,与使用.skip()
和.limit()
修饰符不同,它不能用于“返回”上一页或实际上“跳”至特定页面。至少不需要花费很多精力来存储“可见的”或“发现的”页面,因此,如果您想要的是“链接到页面”页面的类型,那么尽管性能出色,还是最好还是坚持使用.skip()
and
.limit()
方法。缺点。
如果只“前进”是可行的选择,那么这里是基本概念:
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
值存储到present _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 }
您实际持有多少“
seenIds”取决于您的结果在多大程度上可以改变该值。在这种情况下,您可以检查当前的“等级”分数是否不等于该lastSeen
值,并丢弃当前seenIds
内容,以使它不会增长太多。
这是“转发分页”的基本概念,供您练习和学习。
本文向大家介绍mongoDB 实现主从读写分离实现的实例代码,包括了mongoDB 实现主从读写分离实现的实例代码的使用技巧和注意事项,需要的朋友参考一下 mongoDB主从读写分离 MongoDB官方已经不建议使用主从模式了,替代方案是采用副本集的模式, 点击查看。如果您的环境不符合副本集模式可参考本文,来实现主从读写分离。 resources.properties mongo_config.x
我是mongoDb中的一个noob,我需要为任何特定的集合实现分页,例如,比方说 我有一个集合Foo,我有一个函数从Foo集合返回所有记录 但是我需要通过实现分页从Foo获取记录,我如何使用mongoTemplate Spring data MongoDB来实现这一点呢?
我遵循下面的指导方针在我的Quarkus服务器应用程序中实现MongoDB ORM。 例如:如果我有两个实体,如Employee,Organization,那么我如何在Employee实体中引用Organization?
问题内容: 我是ReactJS的新手,正在其中创建一个简单的TODO应用程序。实际上,这是一个非常基本的应用程序,没有数据库连接,任务存储在数组中。我现在想添加分页功能,并添加了“编辑和删除”功能。如何实施?任何帮助将不胜感激。谢谢…!! 问题答案: 我最近在纯React JS中实现了分页。这是一个工作示例:http : //codepen.io/PiotrBerebecki/pen/pEYPbY
我读到过,在中包含异步是async/await的反模式。下面的代码可以工作,但是我想知道如果没有中的,如何实现相同的结果。 谢了。
如何在Struts 2中为客户端显示实现分页,并将Hibernate作为持久层。 以下是我迄今为止完成的代码: 有没有办法在没有标签的情况下实现这一点?