游标
用var声明一个变量,用于保存查询的结果。
var cursor=db.users.find();
上述语句之后,cursor其实并没有获取到users中的文档,而是申明一个“查询结构”,等我们需要的时候通过
for或者next()一次性加载过来,然后让游标逐行读取,当我们枚举完了之后,
游标销毁,之后我们在通过curs获取时,
发现没有数据返回了。
通过curso.hasNext()检查是否有后续结果存在,然后用cursor.next() 将其获得。
"查询构造":
db.users.find().limit(3):返回三个匹配的文档。
db.users.find().skip(3):略过前三个匹配的文档,然后返回其他。
db.users.find().sort("name",1):按name升序返回结果,-1降序。
注意:避免使用skip()略过大量的结果。其处理速度很慢。
不用skip对结果分页:
以"date"降序显示文档,获取结果的第一页:
var page1=db.users.find().sort({"date":-1}).limit(100)
可以利用最后一个文档中"date“的值作为查询条件,来获取下一页:
var lastest=null;
//display first page
while(page1.hasNext()){
latest=page1.next();
display(latest);
}
//get next page
var page2=db.users.find({"date":{"$gt":latest.date}});
page2.sort({"date":-1}).limit(100);
随机选取文档
>//do not use
>var total=db.users.count()
> var random=Math.floor(Math.random()*total)
>db.foo.find().skip(random).limit(1)
这种方法效率很低,不可取。
可以在插入文档的时候,添加一个额外的随机键"andom“:Math.random()
> var random=Math.random()
>result=db.users.findOne({"random":{"$gt":random}})
>if(result==null){
... result=db.users.findOne({"random":{"$lt":random}})
...}
高级查询选项:
- $maxscan:integer 指定查询最多扫描的文档数量
- $min:document 查询开始的条件
- $max:document 查询结束的条件
- $hint:document 指定服务器使用哪个索引进行查询
- $explain:boolean 获取查询执行的细节(用到的索引、结果数量、耗时等),而非真正执行查询。
- $snapshot:boolean 确保查询结果是在查询执行那一刻的一致快照。
聚合
count:返回集合中文档的数目
distinct:找出给定键的所有不同值。
group:
参数介绍:
key: 这个就是分组的key,我们这里是对年龄分组。
initial: 每组都分享一个”初始化函数“,特别注意:是每一组,比如这个的age=20的value的list分享一个
initial函数,age=22同样也分享一个initial函数。
$reduce: 这个函数的第一个参数是当前的文档对象,第二个参数是上一次function操作的累计对象,第一次
为initial中的{”perosn“:[]}。有多少个文档, $reduce就会调用多少次。
下面举的例子就是按照age进行group操作,value为对应age的姓名。
condition 过滤条件
finalize:这是个函数,每一组文档执行完后,都会触发此方法,那么在每组集合里面加上count也就是它的活了。
MapReduce:
count 、distinct、group 能做的事情基本上都能做。可以轻松并行化到多个服务器的聚合方法。它会拆分问题,再将各个部分发送到不同的机器上,让每台机器都完成一部分。所有机器完成的时候,在把结果汇集起来。使用MapReduce的代价就是速度,绝不要用在“实时”的环境中。作为后台任务来运行。
步骤:
- 映射(map):将操作映射到每个文档。操作要么是”无作为“,要么产生一些键值和X个值。里面会调用emit(key,value),集合会按照你指定的key进行映射分组。
- 洗牌(shuffle):按照键值分组,并将产生的键值组成列表放到对应的建中。
- 化简(reduce):则把列表中的值化简为一个单值,并返回。然后接着洗牌,知道每个键的列表只有一个值为止。
注意:在reduce(key,value)中的key就是emit中的key,vlaue为emit分组后的emit(value)的集合,这里也就是很多{"count":1}的数组。
-
mapReduce:这个就是最后执行的函数了,参数为map,reduce和一些可选参数。
以下程序是找出集合中的所有键:
this 是当前映射文档的引用;map函数使用"emit"返回要处理的值。文档为每一个键值调用一次emit。
那样就会返回:{count:1,id:1}、{count:1,id:2}、{count:1,id:3},其中id键用于区别。然后将这两个返回值传给reduce函数。
从图中我们可以看到如下信息:
result: "存放结果的集合名“;
input:传入文档的个数。
emit:此函数被调用的次数。
reduce:此函数被调用的次数。
output:最后返回文档的个数。
最后我们看一下“collecton”集合里面按键分组的情况。