游标
游标,简单的说就是一个查询结果的指针。游标作为数据库的一个对象,使用它是包括
- 声明
- 打开
- 循环抓去一定数目的文档直到结果集中的所有文档已经抓取完
- 关闭游标
游标的基本用法,类似于JDBC的ResultSet(hasNext判断是否抓去完,next移动游标到下一条文档),在获取一个文档集时,可以提供一个类似JDBC的FetchSize作为一次抓取的数据
for(i=0; i<100; i++) { db.c.insert({x : i}); //创建16个文档,每个文档由1个键值对组成 } var cursor = db.c.find(); //打开游标 while (cursor.hasNext()) { //判断游标是否到尾部 obj = cursor.next(); //滚动游标 print(obj.x);//obj是当前游标指向的文档 }
分页
db.c.find().skip(60).limit(10); //查询61-70的文档,如果仅仅指定skip,那么默认的limit是20
分页查询的过程如何,是先执行db.c.find()将所有的结果取出来,再做skip和limt吗?应该不是!
看下db.c.find().skip(60).limit(10)的执行计划:
db.c.find().skip(60).limit(10).explain(); { "cursor" : "BasicCursor", //使用基本游标,未使用索引 "isMultiKey" : false, "n" : 10,//结果集中的文档一共有10 "nscannedObjects" : 10, //扫描文档数目 "nscanned" : 70, //这个70表示什么意思?应该是skip(60).limit(10)之后的70 "nscannedObjectsAllPlans" : 10, "nscannedAllPlans" : 70, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { }, "server" : "tom-Inspiron-3521:27017" }
对照看下db.c.find()的执行计划:
> db.c.find().explain(); { "cursor" : "BasicCursor", "isMultiKey" : false, "n" : 100,//结果中包含的文档数 "nscannedObjects" : 100, //扫描的文档数 "nscanned" : 100,//这个100表示什么意思? "nscannedObjectsAllPlans" : 100, "nscannedAllPlans" : 100, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { }, "server" : "tom-Inspiron-3521:27017" }
查询结果排序
使用测试数据
var p1 = { "name":"Jack", "age":34, "nickname":"xiaoqiang", friends:[ {"name":"Cloe","age":"28"}, {"name":"Audrey","age":"31"}, ] } var p2 = { "name":"Cloe", "age":28, friends:[ {"name":"Jack","age":"34"}, {"name":"Mike","age":"31"}, ] } var p3 = { "name":"Audrey", "age":31, friends:[ {"name":"Jack","age":"34"}, {"name":"Hammer","age":"61","relation":"parent"}, ] }
按照年龄排序
db.people.drop(); db.people.insert(p1); db.people.insert(p2); db.people.insert(p3); db.people.find().sort({"age":-1}); //降序 db.people.find().sort({"age":-1}); //升序