MongoDB游标

查询结果返回过程
使用find函数进行查询时,MongoDB并不是一次返回结果集中的所有文 档,而是以多条文档的形式分批来返回查询结果,返回的文档会缓存到内存中。 这种批量返回结果的好处是,一方面,它可以减少客户端对服务器连接 次数,从而减轻服务器的查询负担;另一方面,当查询结果集很大时,批量返 回结果的方式可以减少客户端的等待时间,提高数据的处理效率。

游标介绍及使用
在MongoDB中,提供了类似关系型数据的游标cursor对象,使用它 来遍历结果集中的数据。
针对游标,MongoDB提供了许多函数,主要包括
方法名 功能 方法名 功能
hasNext 判断是否还有更多的文档 sort 对查询结果进行排序
next 用来获取下一条文档 objsLeftInBatch
查看当前批次剩余的未被迭代 的文档数量
toArray 将查询结果放到数组中 addOption
为游标设置辅助选项,修改游 标的默认行为
count 获取结果集中总的文档数量 hint 为查询强制使用指定索引
limit 限制结果返回数量 explain 用于获取查询执行过程报告
skip 跳过指定数目的文档 snapshot 对查询结果使用快照
使用游标时,需要注意下面几个问题
  • 当调用find函数时,shell并不立即查询数据库,而是等真正开始获取结果时才发送查询请求
  • 游标对象的每个方法几乎都返回游标对象本身,这样就可以方便的进行链式函数调用
  • MongoDB Shell中使用游标输出文档包含两种情况:
    • 自动迭代 如果不将find函数返回的游标赋值给一个局部变量进行保存的话,默认情况下游标会自动迭代20次
    • 手动迭代 将find函数返回的游标赋值给一个局部变量,然后使用游标对象提供的函数进行手动迭代
  • 使用清空后的游标,进行迭代输出时,显示内容为空
游标的生命周期
一个游标从创建到被销毁的整个过程存在的时间,称为游标的生命周期,它 包括游标的创建、使用以及销毁三个阶段。 当客户端使用find函数向服务器端发起一次查询请求时,会在服务器端创 建一个游标,然后就可以使用游标函数来操作查询结果。
下面三种情况会让游标销毁:
  • 游标遍历完成后,或者客户端主动发送终止消息
  • 客户端保存的游标变量不在作用域内
  • 在服务器端10分钟内未对游标进行操作
关于游标的生命周期,需要说明:
  • 有时希望游标存在时间长一些,避免这种“超时销毁”的行为,可以使用addOption函数为游标添加noTimeout的选项:
 
    
var mycurosr = db.collection.find().addOption(DBQuery.Option.noTimeout);
  • 使用serverStatus()函数可以查看当前系统的游标状态
 
   
db.serverStatus().metrics.cursor{
"timed0ut":<number>,
"open":{
"noTimeout":<number>,
"pinned":<number>,
"total":<number>
}
}

游标快照的介绍及使用
MongoDB的游标在整个生命周期中不具有隔离性(isolated),当查询结果 集很大且在查询结果集上执行数据更新操作时,可能会多次返回同一个文档。 游标可能会返回那些由于由于体积变大而被移动到集合末尾的文档,解决这 个问题的方法是对查询进行快照(snapshot)。其语法如下
 
    
db.collection.find().snapshot()
使用快照后,查询就会在_id索引上来遍历执行,这样就可以保证每个文档 只会被返回一次,从而保证获取结果的一致性。

游标实例
 
   
//连接数据库
db = connect("localhost:27017/test");
 
//清空测试集合
db.query_cursor.drop();
 
for (i=0;i<20;i++)
{
db.query_cursor.insert({index:i,text:"Hello MongoDB!"});
}
 
//测试用例
print("========游标的使用---基本使用========")
var cursor = db.query_cursor.find({},{_id:0,index:1 });
 
// 跳过前15个元素
cursor.skip(15);
 
 
while (cursor.hasNext())
{
var obj = cursor.next();
print(tojson(obj));
 
var left = cursor.objsLeftInBatch();
print("Left in bash:",left);
}
 
 
 
print("========游标---toArray函数的使用========")
/*
函数原型:db.collection.find().toArray()
*/
var documentArray = db.query_cursor.find().toArray()
if (documentArray.length > 10)
{
var obj = documentArray[10];
printjson(obj)
}
 
 
 
 
print("========游标的使用---forEach函数的使用========")
/*
函数原型:db.collection.find().forEach(<function>)
*/
var cursor = db.query_cursor.find()
cursor.forEach( function(temp)
{
if (temp.index ==10)
{
print("test.index: " + temp.index+
" test.obj: " + temp.text )
}
})
 
 
 
print("========游标的使用---查看系统游标状态========")
var cursor_status = db.serverStatus().metrics.cursor
printjson(cursor_status)
 
运行结果如下:
 
   
C:\>mongo --quiet query_cursor.js
========游标的使用---基本使用========
{ "index" : 15 }
Left in bash: 4
{ "index" : 16 }
Left in bash: 3
{ "index" : 17 }
Left in bash: 2
{ "index" : 18 }
Left in bash: 1
{ "index" : 19 }
Left in bash: 0
========游标---toArray函数的使用========
{
"_id" : ObjectId("56e95db157f9114c1ae54c93"),
"index" : 10,
"text" : "Hello MongoDB!"
}
========游标的使用---forEach函数的使用========
test.index: 10 test.obj: Hello MongoDB!
========游标的使用---查看系统游标状态========
{
"timedOut" : NumberLong(0),
"open" : {
"noTimeout" : NumberLong(0),
"pinned" : NumberLong(0),
"total" : NumberLong(0)
}
}

猜你喜欢

转载自blog.csdn.net/u022812849/article/details/51314803