MongoDB 游标

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: MongoDB中的游标与关系型数据库中的游标在功能上大同小异。游标相当于C语言的指针,可以定位到某条记录,在MongoDB中,则是文档。

MongoDB中的游标与关系型数据库中的游标在功能上大同小异。游标相当于C语言的指针,可以定位到某条记录,在MongoDB中,则是文档。因此在mongoDB中游标也有定义,声明, 打开,读取,关闭这么个过程。客户端通过游标,能够实现对最终结果进行有效的控制,诸如限制结果数量,跳过部分结果或根据任意键按任意顺序的组合对结果进行各种排序等。下文是针对MongoDB游标的具体介绍。

一、mongoDB游标介绍

    db.collection.find()方法返回一个游标,对于文档的访问,我们需要进行游标迭代
    mongoDB的游标与关系型数据库SQL中的游标类似,可以通过对游标进行(如限制查询结果数,跳过的结果数等)设置来控制查询结果
    游标会消耗内存和相关系统资源,游标使用完后应尽快释放资源
    在mongo shell中,如果返回的游标结果集未指定给某个var定义的变量,则,游标自动迭代20次,即输出前20个文档,超出20的情形则需要输入it来翻页
    本文内容描述手动方式来实现游标迭代来访问文档或者是用索引迭代

    声明游标
            var cursor =  db.collectioName.find(query,projection);

    打开游标
            Cursor.hasNext() 判断游标是否已经取到尽头

    读取数据
            Cursor.Next()    取出游标的下一个文档

    关闭游标
            cursor.close()   此步骤可省略,通常为自动关闭,也可以显示关闭

    用while循环来遍历游标示例
            var mycursor = db.bar.find({_id:{$lte:5}})
            while(mycursor.hasNext()) {
                    printjson(mycursor.next());
                    }

    游标生命周期
            a、游标完成匹配结果的迭代后,它会清除自身;
            b、客户端的游标已经不在作用域内,驱动程序回向服务器发送一条特别的消息,让其销毁;
            c、缺省情况下,游标在十分钟内没有使用,游标自动关闭或者客户端已经迭代完整个游标;
            d、可以通过cursor.noCursorTimeout()来定义游标超时时间
                    如:var myCursor = db.users.find().noCursorTimeout()
            e、对于自定义超时时长的游标可以使用cursor.close() 来关闭游标
                    如:db.collection.find(<query>).close()

二、当前环境及数据准备

    repSetTest:PRIMARY> db.version()
    3.0.12
    //创建包含29个文档的集合user
    repSetTest:PRIMARY> for (var i=1;i<30;i++){
    ... db.user.insert({"id":i,"ename":"usr"+i});
    ... }
    WriteResult({ "nInserted" : 1 })
    repSetTest:PRIMARY> db.user.count()
    29

    //查询集合user上所有文档
    repSetTest:PRIMARY> db.user.find()
    { "_id" : ObjectId("5804d07fd974b32430ea9748"), "id" : 1, "ename" : "usr1" }
    { "_id" : ObjectId("5804d07fd974b32430ea9749"), "id" : 2, "ename" : "usr2" }
               .............................
    { "_id" : ObjectId("5804d07fd974b32430ea975b"), "id" : 20, "ename" : "usr20" }
    Type "it" for more   //上面的结果只输出了20行,这个提示表明查看更多应输入it

    repSetTest:PRIMARY> it
    { "_id" : ObjectId("5804d07fd974b32430ea975c"), "id" : 21, "ename" : "usr21" }
      ..............
    { "_id" : ObjectId("5804d07fd974b32430ea9764"), "id" : 29, "ename" : "usr29" }

二、使用print输出游标结果集

    repSetTest:PRIMARY> var myCursor = db.user.find()
            while (myCursor.hasNext()) {
            print(tojson(myCursor.next()))
    }

    { "_id" : ObjectId("5804d07fd974b32430ea9748"), "id" : 1, "ename" : "usr1" }
          ..........
    {
            "_id" : ObjectId("5804d07fd974b32430ea9751"),
            "id" : 10,
            "ename" : "usr10"
    }
         ................
    {
            "_id" : ObjectId("5804d07fd974b32430ea9764"),
            "id" : 29,
            "ename" : "usr29"
    }
    //上述查询中通过var myCursor进行变量的定义,相当于SQL中的declare cursor cur_name is select ..
    //变量 myCursor定义仅仅是定义,并不会访问数据库,而是在myCursor.hasNext()真正访问数据库
    //myCursor.next()则是输出下一条记录,hasNext()访问数据库时会根据缺省游标设定将结果读取到本地

三、使用printjsont输出游标结果集

    repSetTest:PRIMARY> var myCursor = db.user.find({id:{$gt:20}})
            while (myCursor.hasNext()) {
            printjson(myCursor.next());}
    {
            "_id" : ObjectId("5804d07fd974b32430ea975c"),
            "id" : 21,
            "ename" : "usr21"
    }
              .......
    {
            "_id" : ObjectId("5804d07fd974b32430ea9764"),
            "id" : 29,
            "ename" : "usr29"
    }

四、使用 forEach()进行迭代

    repSetTest:PRIMARY> var myCursor = db.user.find({id:{$gt:20}})
    repSetTest:PRIMARY> myCursor.forEach(printjson);
    {
            "_id" : ObjectId("5804d07fd974b32430ea975c"),
            "id" : 21,
            "ename" : "usr21"
    }
            ................
    {
            "_id" : ObjectId("5804d07fd974b32430ea9764"),
            "id" : 29,
            "ename" : "usr29"
    }

五、基于数组索引迭代

    可以使用toArray()将游标迭代文档返回到一个数组,然后通过数组下标方式进行访问。
    该方法将所有由游标返回的文档装载进内存。

    //如下示例,将游标返回的内容传递到数组,然后使用 printjson (documentArray[3])输出其中的元素
    repSetTest:PRIMARY> var myCursor = db.user.find({id:{$gt:20}})
    repSetTest:PRIMARY> var documentArray = myCursor.toArray();
    repSetTest:PRIMARY> printjson (documentArray[3])
    {
            "_id" : ObjectId("580d775edeb57e4d05eec0f2"),
            "id" : 24,         //Author : Leshami
            "ename" : "usr24"  //Blog   : http://blog.csdn.net/leshami
    }

    //也可以将数组元素输出到某个变量,然后在用printjson(myDocument)输出这个变量,如下
    repSetTest:PRIMARY> var myDocument = documentArray[3];
    repSetTest:PRIMARY> printjson(myDocument)
    {
            "_id" : ObjectId("580d775edeb57e4d05eec0f2"),
            "id" : 24,
            "ename" : "usr24"
    }

六、调整游标迭代次数

    //设置迭代显示的次数,如下设置为5
    repSetTest:PRIMARY> DBQuery.shellBatchSize = 5
    5
    repSetTest:PRIMARY> db.user.find()
    { "_id" : ObjectId("5804d07fd974b32430ea9748"), "id" : 1, "ename" : "usr1" }
    { "_id" : ObjectId("5804d07fd974b32430ea9749"), "id" : 2, "ename" : "usr2" }
    { "_id" : ObjectId("5804d07fd974b32430ea974a"), "id" : 3, "ename" : "usr3" }
    { "_id" : ObjectId("5804d07fd974b32430ea974b"), "id" : 4, "ename" : "usr4" }
    { "_id" : ObjectId("5804d07fd974b32430ea974c"), "id" : 5, "ename" : "usr5" }
    Type "it" for more  //从上面的查询结果可知,当输出5个文档就提示需要输入it来查看更多
    repSetTest:PRIMARY> it
    { "_id" : ObjectId("5804d07fd974b32430ea974d"), "id" : 6, "ename" : "usr6" }
    { "_id" : ObjectId("5804d07fd974b32430ea974e"), "id" : 7, "ename" : "usr7" }
    { "_id" : ObjectId("5804d07fd974b32430ea974f"), "id" : 8, "ename" : "usr8" }
    { "_id" : ObjectId("5804d07fd974b32430ea9750"), "id" : 9, "ename" : "usr9" }
    { "_id" : ObjectId("5804d07fd974b32430ea9751"), "id" : 10, "ename" : "usr10" }
    Type "it" for more

七、查看游标度量信息

    可以通过db.serverStatus()查看游标状态相关的信息,这些信息通常包括
            从服务器上次启动之后游标超时的数量
            自定义游标超时的数量
            游标打开后已经pinned的数量
            打开游标的总数目
    //如下查询本机游标的信息       
    repSetTest:PRIMARY> db.serverStatus().metrics.cursor
    {
            "timedOut" : NumberLong(2),
            "open" : {
                    "noTimeout" : NumberLong(0),
                    "pinned" : NumberLong(0),
                    "total" : NumberLong(2)
            }
    }
相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
NoSQL MongoDB 数据库
4种方法解决MongoDB游标超时的问题
4种方法解决MongoDB游标超时的问题
571 0
|
NoSQL Shell MongoDB
MongoDB(15)- 查询操作里面的游标 cursor
MongoDB(15)- 查询操作里面的游标 cursor
394 0
MongoDB(15)- 查询操作里面的游标 cursor
|
关系型数据库 MySQL PHP
|
存储 JavaScript NoSQL
《MongoDB管理与开发精要》——3.4节游标和存储过程
本节书摘来自华章社区《MongoDB管理与开发精要》一书中的第3章,第3.4节游标和存储过程,作者:红 丸,更多章节内容可以访问云栖社区“华章社区”公众号查看
1392 0
|
SQL NoSQL JavaScript
mongoDB查询及游标
find文档 1.find简介 使用find查询集合中符合条件的子集合 1 db.test.blog.find(); 类似于sql查询 1 select * from test.blog   上面的查询是返回多有多有集合,并且是所有键。
1475 0
|
NoSQL 关系型数据库 数据库
3.非关系型数据库(Nosql)之mongodb:升降序排序,排序分页,$all,$in,$nin,$or,$nor, $exists,游标,更新(update,$set,$unset,$inc)
 1排序sort() A降序排列 db.c4.find().sort().sort({age:-1}); B升序排列: db.c4.find().sort({age:-1}); C排序分页 db.collectionName.find().sort({age:-1}).skip(2
1268 0
|
2月前
|
存储 关系型数据库 MySQL
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景比较
|
1月前
|
NoSQL Cloud Native atlas
探索云原生数据库:MongoDB Atlas 的实践与思考
【10月更文挑战第21天】本文探讨了MongoDB Atlas的核心特性、实践应用及对云原生数据库未来的思考。MongoDB Atlas作为MongoDB的云原生版本,提供全球分布式、完全托管、弹性伸缩和安全合规等优势,支持快速部署、数据全球化、自动化运维和灵活定价。文章还讨论了云原生数据库的未来趋势,如架构灵活性、智能化运维和混合云支持,并分享了实施MongoDB Atlas的最佳实践。