当前位置:首页 > 开发 > 研发管理 > 正文

MongoDB查询(4)——游标和分页[八]

发表于: 2015-01-20   作者:eksliang   来源:转载   浏览:
摘要: 转载请出自出处:http://eksliang.iteye.com/blog/2177567 一、游标         数据库使用游标返回find的执行结果。客户端对游标的实现通常能够对最终结果进行有效控制,从shell中定义一个游标非常简单,就是将查询结果分配给一个变量(用var声明的变量就是局部变量),便创建了一个游标,如下所示: > var

转载请出自出处:http://eksliang.iteye.com/blog/2177567

一、游标

        数据库使用游标返回find的执行结果。客户端对游标的实现通常能够对最终结果进行有效控制,从shell中定义一个游标非常简单,就是将查询结果分配给一个变量(用var声明的变量就是局部变量),便创建了一个游标,如下所示:

> var cursor = db.users.find()

       这么做的好处就是可以一次查看一条结果。如果将上面查询结果放在全局变量中或者根本就没有放在变量中,MongoDB shell会自动迭代,自动显示最开始的若干文档。

 

可以使用游标的next()方法获得下一条数据。使用hasNext()方法查看游标里面是否还有数据。

参考实例一:while迭代游标

var cursor = db.users.find().limit(10);
while(cursor.hasNext()){
	user=cursor.next();
	print(user.name);
}

 参考实例二:forEach迭代游标

var cursor = db.users.find().limit(10);
cursor.forEach(function(user){
	print(user.name);
});

       调用find()方法时,shell并不立即查询数据库,而是等待真正开始要求获得结果时才发送查询,这样在执行之前可以给查询附加额外的选项。几乎游标对象的每个方法都返回游标本身,这样就可以按任意顺序组成方法链。例如,下面几种表达式是等价的。

> var cursor=db.users.find().sort({"age":1}).limit(10).skip(10)
> var cursor=db.users.find().skip(10).limit(10).sort({"age":1})

       此时上面的查询还没有向数据库发送请求,他们只是在构造查询。现在,假设我们执行如下操作:

> cursor.hasNext()

      这时,查询被发往服务器。shell立刻获得100条数据或者前4M数据(两种之间取小者),这样下次调用next或者hasNext时就不必再次连接服务器获取结果了。当客户端用光了第一组结果,shell会再一次联系数据库。

 

二、游标的生命周期

       看待游标有两种角度:“客户端游标”以及“客户端请求过去的服务器端游标”,在服务器端,游标消耗内存和其他资源。所以我们讨论就讨论服务器端的,客户端的没有什么意义。当客户端向服务器发起一次查询find()就代表在服务器端创建了一个游标,下面三种情况会让游标销毁。

  • 当游标遍历尽了以后,或者客户端发来消息要求终止,数据库会释放这些资源。
  • 当客户端的游标不在作用域内时,驱动程序会向服务器发送一条特别消息,让其销毁游标。
  • 当服务器端10分钟以内不对游标进行操作,即使客户端游标在作用域内或者还没有迭代完,数据库也会自动销毁游标。

三.、imit、skip和sort

  • limit:用来限制返回的结果,返回匹配文档的上限
  • skip:跳过前面多少个文档
  • sort:  排序的参数

这些选项必须在查询发送到服务器之前指定

参考实例:分页查询users集合的第二页每页10条记录,并指定对age进行升序

> var cursor=db.users.find().skip(10).limit(10).sort({"age":1})
> cursor.forEach(function(user){
... print("userName:"+user.name+" age:"+user.age);
... });

 返回结果如下:

userName:user2088 age:11
userName:user2212 age:12
userName:user2371 age:13
userName:user2655 age:14
userName:user2681 age:15
userName:user2855 age:16
userName:user3186 age:17
userName:user3332 age:18
userName:user3383 age:19
userName:user3465 age:20

 

 

 四、怎么对mongodb进行分页

      当使用skip略过少量文档还是不错的。但是要是数量非常多的话,skip会变得相当慢,例如想返回第10000页(每页20条记录),MongoDB必须先找到200000条记录,然后再抛弃199920条数据,这种分页需求在业内也有一个名词叫做“深分页”。大多数数据库都会再索引中保存更多的元数据,用于处理skip(Solr 4.7.1也引入了游标处理这种深分页),所以要尽量避免滤过太多数据。

 

既然MongoDB的skip不适合做深分页,那怎么做呢?

答:MongoDB能不能做深分页这取决于查询本身。

根据一般业务来讲,可以找到一种方法在不使用skip的情况下实现分页,这主要取决于查询本身。

参考实例

例如要按照"date"降序显示文档列表。可以按照如下方式获取结果的第一页:

> db.users.find().sort({"create":-1}).limit(10)

 然后利用上次查询的最后一个文档中的"date"值作为查询条件,来获取下一页:

var lastTime=users.last.date;--这个可以根据实际情况获得,我这里只是随便写写,让你感受到这种思想。

获取下一页:

db.users.find({"create":{"$gt":lastTime}}).sort("create":-1}).limit(10)

 这种分页查询中就没有了skip了。

 

优化深分页的核心思想(包括关系型数据库,以及其他NoSql数据库):减少当前查询在结果集里面存放的数据。

 

 

 

 

 

 

MongoDB查询(4)——游标和分页[八]

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
前言 在上一篇Node.js、express、mongodb 入门(基于easyui datagrid增删改查) 的基础上实现了分页查
在NoSQL数据库中游标的概念与关系型数据库差不多,主要是为了达到延长执行的效果。客户端通过对游标
转自 http://www.cnblogs.com/egger/archive/2013/06/14/3135847.html  本文将介绍操作符的使用,
在关系数据库中,我们对于查询的思考是面向集合的,而游标打破了这一规则,游标使得我们思考方式变
1、概述 2、分业查询 <img src="http://img.it610.com/image/info2/5506792e22944edc951874c8efa
MongoDB的分页性能是广大使用者所诟病的大问题之一,在大数据量环境下,如果一次跳转的页数过多,如
1.$where where可以接受一个javascript函数作为查询条件,并且迭代当前集合里面的所有文档,如果满
在建立数据库,输入数据的前提下,用db.rawQuery(sql,selectionArgs)联系接口Cursor c; 然后运
分享下mongodb中关于索引的基本操作,我们日常做开发都避免不了要对程序进行性能优化,而程序的操作
游标的使用 在mongo shell中,读操作的主要方法是db.collection.find(),该方法查询一个集合并一个包
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号