MongoDB 游标详解及实例代码

 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)
      }
  }

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • MongoDB中游标的深入学习

    前言 MongoDB中的游标与关系型数据库中的游标在功能上大同小异.游标相当于C语言的指针,可以定位到某条记录,在MongoDB中,则是文档.因此在mongoDB中游标也有定义,声明, 打开,读取,关闭这么个过程.客户端通过游标,能够实现对最终结果进行有效的控制,诸如限制结果数量,跳过部分结果或根据任意键按任意顺序的组合对结果进行各种排序等. 通俗的说,游标不是查询结果,可以理解为数据在遍历过程中的内部指针,其返回的是一个资源,或者说数据读取接口. 客户端通过对游标进行一些设置就能对查询结果进行

  • mongodb数据库游标的使用浅析

    mongodb中的游标使用示例如下:   假设执行如下操作: db.XXX.remove(); db.XXX.insert({"name":"BuleRiver1", "age":27}); db.XXX.insert({"name":"BuleRiver2", "age":23}); db.XXX.insert({"name":"BuleRiver3&qu

  • MongoDB入门教程之聚合和游标操作介绍

    今天跟大家分享一下mongodb中比较好玩的知识,主要包括:聚合,游标. 一: 聚合 常见的聚合操作跟sql server一样,有:count,distinct,group,mapReduce. <1> count count是最简单,最容易,也是最常用的聚合工具,它的使用跟我们C#里面的count使用简直一模一样.  <2> distinct 这个操作相信大家也是非常熟悉的,指定了谁,谁就不能重复,直接上图.  <3> group 在mongodb里面做group操作

  • MongoDB 游标详解及实例代码

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

  • MyBatis获取数据库自生成的主键Id详解及实例代码

    MyBatis获取数据库自生成的主键Id详解及实例代码 在使用MySQL数据库时我们一般使用数据库的自增主键自动产生主键.如果在插入主表时,我们需要同时插入从表的数据,这时我们通常需要知道主表插入时自动产生的主键Id值. 下面介绍使用MyBatis进行插入时,如何同时获取数据库自生成的主键: 1.XML配置文件 <insert id="insert" parameterType="Person" useGeneratedKeys="true"

  • MySQL 序列 AUTO_INCREMENT详解及实例代码

    MySQL 序列 AUTO_INCREMENT详解及实例代码 MySQL序列是一组整数:1, 2, 3, ...,由于一张数据表只能有一个字段自增主键, 如果你想实现其他字段也实现自动增加,就可以使用MySQL序列来实现. 本章我们将介绍如何使用MySQL的序列. 使用AUTO_INCREMENT MySQL中最简单使用序列的方法就是使用 MySQL AUTO_INCREMENT 来定义列. 实例 以下实例中创建了数据表insect, insect中id无需指定值可实现自动增长. mysql>

  • Java 两种延时thread和timer详解及实例代码

    Java 两种延时thread和timer详解及实例代码 在Java中有时候需要使程序暂停一点时间,称为延时.普通延时用Thread.sleep(int)方法,这很简单.它将当前线程挂起指定的毫秒数.如 try { Thread.currentThread().sleep(1000);//毫秒 } catch(Exception e){} 在这里需要解释一下线程沉睡的时间.sleep()方法并不能够让程序"严格"的沉睡指定的时间.例如当使用5000作为sleep()方法的参数时,线 程

  • Spring组件自动扫描详解及实例代码

    Spring组件自动扫描详解及实例代码 问题描述 一个系统往往有成千上万的组件,如果需要手动将所有组件都纳入spring容器中管理,是一个浩大的工程. 解决方案 Spring 提供组件扫描(component scanning)功能.它能从classpath里自动扫描.侦测和实例化具有特定注解的组件.基本的注解是@Component,它标识一个受Spring管理的组件.其他特定的注解有@Repository.@Service和@Controller,它们分别标识了持久层.服务处和表现层的组件.

  • Java中自定义异常详解及实例代码

    Java中自定义异常详解及实例代码 下面做了归纳总结,欢迎批评指正 自定义异常 class ChushulingException extends Exception { public ChushulingException(String msg) { super(msg); } } class ChushufuException extends Exception { public ChushufuException(String msg) { super(msg); } } 自定义异常 En

  • Spring AOP 基于注解详解及实例代码

    Spring AOP  基于注解详解及实例代码 1.启用spring对@AspectJ注解的支持: <beans xmlns:aop="http://www.springframework.org/schema/aop"...> <!--启动支持--> <aop:aspectj-autoproxy /> </beans> 也可以配置AnnotationAwareAspectJAutoProxyCreator Bean来启动Spring对@

  • java多线程编程技术详解和实例代码

     java多线程编程技术详解和实例代码 1.   Java和他的API都可以使用并发. 可以指定程序包含不同的执行线程,每个线程都具有自己的方法调用堆栈和程序计数器,使得线程在与其他线程并发地执行能够共享程序范围内的资源,比如共享内存,这种能力被称为多线程编程(multithreading),在核心的C和C++语言中并不具备这种能力,尽管他们影响了JAVA的设计. 2.   线程的生命周期 新线程的生命周期从"新生"状态开始.程序启动线程前,线程一直是"新生"状态:

  • JS 实现计算器详解及实例代码(一)

    Javascript 实现计算器: 系列文章: JS 实现计算器详解及实例代码(一) Javascript 实现计算器时间功能详解及实例(二) 小型JavaScript计算器 自己寻思出的解决方案,比较笨拙的方法,虽然完成了但是还有不少bug,用的方法也不是最有效的,基本功能算是完成了,一些小的细节地方也考虑到了,但是还有其他的细节需要处理. 总体设计思路是,先画草图 -> 设计UI -> 编写UI代码 -> 编写CSS -> 编写JS逻辑代码: 面板(main-board) 面板

  • java 单播、广播、组播详解及实例代码

    java 单播.广播.组播详解及实例代码 在当前网络通信中(TCP/IP也不例外)有三种通信模式:单播.广播.组播(又叫多播, 个人感觉叫多播描述的有点不恰当),其中多播出现的时间最晚,但同时具备单播和广播的优点,最具有发展前景. 一.通信方式分类: 1.单播:单台主机与单台主机之间的通信: 2.广播:单台主机与网络中所有主机的通信: 3.组播:单台主机与选定的一组主机的通信: 二.单播:    单播是网络通信中最常见的,网络节点之间的通信 就好像是人们之间的对话一样.如果一个人对另外一个人说话

随机推荐