MongoDB游标

MongoDB数据库使用游标返回 find 的执行结果。客户端对游标的实现通常能够对最终结果进行有效的控制,可以限制结果的数量,略过部分结果,根据任意键按任意顺序的组合对结果进行各种排序,或者是执行其他一些强大的操作。

> var cursor = db.mycollection.find();

这查询的结果就放在 cursor 变量中了,可以一次查看一条结果。而如果没有放在变量中,shell 就会自动迭代,自动显示最开始的若干文档。
使用游标的 next() 方法,也可以 hasNext() 方法来查看游标中是否还有其他结果。

> while(cursor.hasNext()){
        obj = cursor.next();
        // do something
    }

游标还可以在 forEach 循环中使用。

> var cursor = db.mycollection.find();
> cursor.forEach(function(x){
        print(x.name);
    })

得到结果

foobar
foo
foo1
foo2
foo3
foo22
foo33

当调用 find() 时,shell 并不立即查询数据库,而是等待真正开始要求获取结果时才发送查询。几乎游标对象的所有方法都返回游标本身,可以按任意顺序组成方法链。
当查询被发往服务器后,shell 立刻获取前 100 个结果或者前 4MB 数据,两者取较小者。这样下次调用 next 或者 hasNext 方法时就不用再连接服务器取结果了。客户端用完了第一次的查询结果,shell 再次联系数据库, 使用 getMore 请求提取更多的结果。 getMore 请求包含一个查询标识符,向数据库询问是否还有更多的结果,如果有,返回下一批结果。这个过程会一直持续到游标耗尽或者结果全部返回。

查询选项

limit

限制结果的数量,可在 find 后使用 limit 函数。只返回3个结果,可以

> db.mycollection.find().limit(3);

如果要略过前3个匹配的文档,返回剩下的文档:

> db.mycollection.find().skip(3);

总数少于3个则不返回任何结果。
要进行排序,使用sort,对应的键 1 为升序,-1 为降序。如对名字进行升序排列:

> db.mycollection.find().sort({"name":1});

比如每页返回20个结果,按照价格从低到高排序:

> db.mycollection.find().limit(20).sort({"price":1});

点击下一页,查看更多结果,通过 skip 可以实现

> db.mycollection.find().limit(20).skip(20).sort({"price":1});

但是,略过过多的结果会导致性能问题,因为要先找到需要被略过的数据,然后再抛弃这些数据。大多数数据库会在索引中保存更多的元数据,用于处理skip,但是MongoDB目前不支持。通常可以利用上一次的结果来计算下一次查询的条件。
条件查询+排序+限制返回记录。边查询,边排序,排序之后,抽取第一次分页中的最后一条记录,最后第二次分页的条件,进行条件查询,以此类推….
比如上例,第一页最后的 price 记录下来比如为100,那么第二页的可以这么改写,但实际中可能并不恰当:

> db.mycollection.find({"price":{$gt:100}}).limit(20).sort({"price":1});

分页这里限制条件可能会遇到条件限制不合理导致重复数据的情况。比如有很多文档有相同的值的情况。除非是以 _id 来进行排序和分页展示,或者以都不相同的所有值的键的情况下。这里《MongoDB权威指南》和网上的众多资料中没有给出好的方案,待之后补充。

游标生命周期

在服务器端,游标消耗内存和其他资源。游标遍历尽了结果以后,或者客户端发来消息求终止,数据库将会释放这些资源。所以要保证尽快释放游标。
当游标完成匹配结果的迭代时,游标会清除自身;如果客户端的游标已经不在作用域内,驱动程序会向服务器发送信息使其销毁游标。另外一个游标10分钟内没有使用的话,也会自动销毁。多数驱动程序可以设置游标的超时时间。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值