MongoDB聚合 互动版

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器

找出集合中的所有键

MongoDB没有模式,所以并不知晓每个文档有多少个键.通常找到集合的所有键的做好方式是用MapReduce。 在映射阶段,想得到文档中的每个键.map函数使用emit 返回要处理的值.emit会给MapReduce一个键和一个值。 这里用emit将文档某个键的记数(count)返回({count:1}).我们为每个键单独记数,所以为文档中的每一个键调用一次emit。 this是当前文档的引用:

> map=function(){ 
... for(var key in this){ 
...      emit(key,{count:1}) 
... }};

这样返回了许许多多的{count:1}文档,每一个都与集合中的一个键相关.这种有一个或多个{count:1}文档组成的数组,会传递给reduce函数.reduce函数有两个参数,一个是key,也就是emit返回的第一个值,另一个参数是数组,由一个或者多个与键对应的{count:1}文档组成。

> reduce=function(key,emits){ 
... total=0; 
... for(var i in emits){ 
...     total+=emits[i].count;  
... } 
... return {count:total}; 
... }

reduce要能被反复被调用,不论是映射环节还是前一个化简环节。reduce返回的文档必须能作为reduce的第二个参数的一个元素。如x键映射到了3个文档{"count":1,id:1},{"count":1,id:2},{"count":1,id:3} 其中id键用于区别。MongoDB可能这样调用reduce:

>r1=reduce("x",[{"count":1,id:1},{"count":1,id:2}]) 
{count:2} 
>r2=reduce("x",[{"count":1,id:3}]) 
{count:1} 
>reduce("x",[r1,r2]) 
{count:3}

不能认为第二个参数总是初始文档之一(比如{count:1})或者长度固定。reduce应该能处理emit文档和其他reduce返回结果的各种组合。

总之,MapReduce函数可能会是下面这样:

> mr = db.runCommand({"mapreduce" : "foo", "map" : map,"reduce" : reduce})
{
    "reduce" : "tmp.mr.mapreduce_1266787811_1", // 这是存放MapReduce结果集合名,临时集合连接关闭自动删除
    "timeMillis" : 12,  // 操作花费的时间,单位毫秒
    "count" : {
        "input" :  6  //发往到map函数的文档个数
        "emit"  : 14  //在map函数中emit被调用的次数
        "output" : 5  //结果集合中的文档数量
     },
     "ok" : true
}