第12章:MongoDB-CRUD操做--文档--查询--游标详解

①是什么游标

游标不是查询结果,能够理解为数据在遍历过程当中的内部指针,其返回的是一个资源,或者说数据读取接口.web

客户端经过对游标进行一些设置就能对查询结果进行有效地控制,如能够限制查询获得的结果数量、跳过部分结果、或对结果集按任意键进行排序等!shell

直接对一个集合调用find()方法时,咱们会发现,若是查询结果超过二十条,只会返回二十条的结果,这是由于Mongodb会自动递归find() 返回的游标。数据库

②mongoDB游标介绍

db.collection.find()方法返回一个游标,对于文档的访问,咱们须要进行游标迭代mongoDB的游标与关系型数据库SQL中的游标相似,能够经过对游标进行(如限制查询结果数,跳过的结果数等)设置来控制查询结果json

游标会消耗内存和相关系统资源,游标使用完后应尽快释放资源数组

在mongo shell中,若是返回的游标结果集未指定给某个var定义的变量,则游标自动迭代20次,即输出前20个文档,超出20的情形则须要输入it来翻页服务器

本文内容描述手动方式来实现游标迭代来访问文档或者是用索引迭代spa

 

 

声明游标.net

   var cursor = db.collectioName.find(query,projection);指针

 

 

打开游标code

   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)

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章
相关标签/搜索