Mongodb聚合

1>、聚合框架:使用聚合框架可以对集合中的文档进行变换和组合。基本上,可以用多个构件创建一个管道(pipeline),用于对一连串的文档进行处理。这些构件包括筛选(filtering)、投射(projecting)、分组(grouping)、排序(sorting)、限制(limiting)和跳过(skipping)。

2>、管道操作符:每个操作符都会接受一连串的文档,对这些文档做一些类型转换,最后将转换后的文档作为结果传递给下一个操作符(对于最后一个管道操作符,是将结果返回给客户端)。不同的管道操作符可以按任意顺序组合在一起使用,而且可以被重复任意多次。1、$match:用于对文档集合进行筛选,之后就可以在筛选得到的文档子集上做聚合。在实际使用中应该尽可能将$match放在管道的前面位置,这样做有两个好处:一是可以快速将不需要的文档过滤掉,以减少管道的工作量;二是如果在投射和分组之前执行$match,查询可以使用索引。2、$project:使用$project可以从子文档中提取字段,可以重命名字段,可以指定包含或者不包含一个字段,还可以在这些字段上进行一些有意思的操作。$project操作是从文档选择想要的字段,可以指定包含或者不包含的一个字段。也可以将投射过得字段进行重命名。db.users.aggregate({$project:{"userId":"$_id","_id":0}})结果如下:{result:[{userId:ObjectId("xxx")}]}。重命名时必须明确指出将要重命名的字段排除(如上例中_id:0),否则这个字段的值会被返回两次:一次被标为重命名后的名字(如userId),一次被标为命名前的(如_id)。可以使用这种技术生成字段的多个副本,以便在之后的$group中使用。在对字段进行重命名时,mongodb并不会记录字段的历史名称,因此,应该尽量在修改字段名称之前使用索引。

3>、表达式:1、算术表达式可用于操作数值:.$add:[expr1[,expr2...,exprn]],接受一个或多个表达式作为参数,将这些表达式相加的和作为结果;.$subtract:[expr1,expr2]接受两个参数,用第一个表达式减去第二个表达式作为结果,将差作为结果;.$multiply:[expr1[,expr2...,exprn]]将表达式的值相乘;.$divide:[expr1,expr2],用第一个表达式除以第二个表达式的商作为结果;.$mod:[expr1,expr2],将第一个表达式除以第二个表达式得到的余数作为结果。2、日期表达式:$year、$month、$week、$dayOfMonth、$dayOfWeek、$dayOfYear、$minute、$second,只能对日期类型的字段进行操作,每种日期类型的操作都是类似的:接受一个日期表达式,返回一个数值。3、字符串表达式:$substr:[expr,startOffset,numToReturn],第一个参数expr必须是字符串,这个操作符将会截取字符串的子串(从startOffset字节开始的numToReturn字节,不是字符);$concat:[expr1[,expr2...,exprN],将给定的表达式连接在一起作为结果返回;$toLower:expr,参数expr必须是字符串值,返回小写形式;$toUpper:expr,参数expr必须是字符串值,返回大写形式。4、逻辑表达式:$cmp:[expr1,expr2],比较expr1和expr2。如果expr1等于expr2,返回0;如果expr1<expr2,返回一个负数;如果expr1>expr2,返回一个正数;$strcasecmp:[string1,string2],比较string1和string2,区分大小写;$eq/$ne/$gt/$gte/$lt/$lte:[expr1,expr2],返回比较的结果(true或false);$and:[expr1[,expr2...,exprN]],如果表达式的值都是true,返回true,否则返回false;$or:[expr1[,expr2...,exprN]],只要有任意表达式的值为true,就返回true,否则返回false;$not:expr,对expr取反;$cond:[booleanExpr,trueExpr,flaseExpr],如果booleanExpr的值为true,返回trueExpr,否则返回flaseExpr;$ifNull:[expr,replacementExpr],如果expr是null,返回replacementExpr,否则返回expr。5、$group:$group操作可以将文档依据特定字段的不同值进行分组,它不能对流式工作方式的文档进行处理,必须要等收到所有的文档之后,才能对文档进行分组。$sum:value,对于分组中的每一个文档,将value与计算结果相加;$avg:value返回每个分组的平均值;$max:expr,返回分组内的最大值;$min:expr,返回分组内的最小值;$frist:expr返回分组的第一个值,忽略后面的所有值;$last:expt返回分组的最后一个值。数组操作符:有两个操作符可以进行数组操作,$addToSet:expr,如果当前数组中不包含expr,就将它添加到数组中,再返回的结果集中,每个元素最大只出现一次,而且元素的顺序是不确定的;$push:expr,不管expr是什么值,都将添加到数组中,返回包含所有值得数组。6、$unwind(拆分):可以将数组中的每一个值拆分为单独的文档。如果希望在查询中得到特定的子文档,这个操作符就会非常有用:先使用$unwind得到所有的子文档,在使用$match得到想要的文档。$sort可以根据任何字段进行排序,排序方向可以是1(升序)和-1(降序)。$limit(n):返回结果集中的前n个文档。$skip(n):跳过结果集中的前n个文档,将剩余的文档作为结果返回。应该尽量在管道的开始阶段(执行$project、$group、$unwind操作之前)就将尽可能多的文档和字段过滤掉。管道如果不是直接从原先的集合中使用数据,那就无法在筛选和排序中使用索引,如果可能,聚合管道会尝试对操作进行排序,以便能够有效的使用索引。mongodb不允许单一的聚合操作占用过多的系统内存:如果mongodb发现某个聚合操作占用了20%以上的内存,这个操作就会直接输出错误。如果能够通过$match操作迅速减小结果集的大小,就可以使用管道进行实施聚合。由于管道会不断包含更多的文档,会越来越复杂,所以几乎不可能呢实时得到管道的操作结果。

4>、MapReduce:MapReduce能够在多台服务器之间并行执行,它会将一个大问题拆分为多个小问题,将各个小问题发送到不同的机器上,每台机器只负责完成一部分工作,所有机器都完成时,再将这些零碎的解决方案合并为一个完整的解决方案。MapReduce需要几个步骤:首先是映射(map),将操作映射到集合中的每个文档,这个操作要么“无作为”,要么“产生一些键和X个值”;然后是中间环节,称作洗牌(shuffle),按照键分组,并将产生的键值组成列表放到对应的键中;最后化简(reduce)则把列表中的值化简成一个单值,这个值被返回,然后接着进行洗牌,知道每个键的列表只有一个值为止,这个值也就是最终的结果。命令语法:db.runCommand(

 { mapreduce : 字符串集合名,

   map : 函数,

   reduce : 函数,

   [, query : 文档,发往map函数前先给过渡文档]

   [, sort : 文档,发往map函数前先给文档排序]

   [, limit : 整数,发往map函数的文档数量上限]

   [, out : 字符串,统计结果保存的集合]

   [, keeptemp: 布尔值,链接关闭时临时结果集合是否保存]

   [, finalize : 函数,将reduce的结果送给这个函数,做最后的处理]

   [, scope : 文档,js代码中要用到的变量]

   [, jsMode : 布尔值,是否减少执行过程中BSON和JS的转换,默认true] //注:false时 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可处理非常大的mapreduce,<br>                                    //true时BSON-->js-->map-->reduce-->BSON

   [, verbose : 布尔值,是否产生更加详细的服务器日志,默认true]

 }

);说明:finalize:function可以将reduce的结果发送给这个键,这是整个处理过程的最后一步,它会在最后一个reduce输出结果后执行,然后将结果存到临时集合中,通常来说,finalize是计算平均数、裁剪数组、清楚多余信息的好时机;keeptemp:boolean如果值为true,那么在连接关闭时会将临时结果集合保存下来,否则不保存;out:string输出集合的名称,如果设置了这个选项,系统会自动设置keeptemp:true,默认情况下,mongo会在执行MapReduce时创建一个临时集合,集合名是系统选的一个不太常用的名字,将"mr"、执行MapReduce的集合名、时间戳以及数据库作业ID,用"."连成一个字符串,这就是临时集合的名字,mongodb会在调用的连接关闭时自动销毁这个集合,可以用out选项为临时集合指定一个易读易懂的名字,但是即便你取了一个非常好的名字,mongodb也会在MapReduce的中间过程使用自动生成的集合名,处理完成后,会自动将临时集合的名字更改为你指定的集合名;query:document在发往map函数前,先用指定条件过滤文档;sort:document在发往map前先给文档排序(与limit一同使用非常有用);limit:integer发往map函数的文档数量的上限;scope:document可以再JavaScript代码中使用的变量;verbose:boolean是否记录详细的服务器日志。

例如:>mr=db.runCommand({mapreduce:"foo",map:map,reduce:reduce})

{  

  result:"tmr.mr.mapreduce_1266787811_1",

  timeMillis:12,

  count:{

    input:6,

    emit:14,

    output:5

  },

  ok:true

}MapReduce返回的文档包含很多与操作有关的元信息:result这是存放MapReduce结果的集合名,这是个临时集合,MapReduce的连接关闭后它就被自动删除了;timeMillis操作话费的时间;counts这个内嵌文档主要用作调试,其中包含3个键:input发送到map函数的文档个数,emit在map函数中emit被调用的次数,output结果集合中的文档数量。有时需要对集合的一部分执行MapReduce,只需在传给map函数前使用查询对文档进行过滤就好了,每个传递给map函数的文档都要先反序列化,从BSON对象转换为JavaScript对象。

5>、聚合命令:count()用于返回集合中文档的数量,不论集合有多大,count都会很快返回总的文档数量,也可以给count传递一个查询文档,mongo会计算查询结果的数量;distinct用来找出给定键的所有不同值,使用时必须指定集合和键,例如:db.runCommand({distinct:"people",key:"age"})。group可以执行更复杂的聚合,先选定分组所依据的键,而后mongodb就会将集合依据选定键的不同值分成若干组,然后可以对每一个分组内的文档进行聚合,得到一个结果文档。

db.collection.group({
	key:{field:1},//按什么字段进行分组
	initial:{count:0},//进行分组前变量初始化,该处声明的变量可以在以下回调函数中作为result的属性使用
	cond:{},//类似mysql中的having,分组后的查询返回
	$reduce: function ( curr, result ) { }, //The function takes two arguments: the current document and an aggregation result document for that group.先迭代出分组,然后再迭代分组中的文档,即curr变量就代表当前分组中此刻迭代到的文档,result变量就代表当前分组。
      $keyf:function(doc){},//keyf和key二选一,传入的参数doc代表当前文档,如果分组的字段是经过运算后的字段用到,作用类似mysql中的group by left(‘2015-09-12 14:05:22‘,10);
      finalize:function(result) {}//该result也就是reduce的result,都是代表当前分组,这个函数是在走完当前分组结束后回调;
})

时间: 2024-11-09 04:05:45

Mongodb聚合的相关文章

Mongodb聚合操作之读书笔记

Mongodb聚合操作 读书笔记 mongodb,两种计算聚合pipeline和mapreduce pipeline查询速度快于mapreduce,但MapReduce能够在多台Server上并行执行复杂的聚合逻辑. mongodb不允许Pipeline的单个聚合操作占用过多的系统内存,如果一个聚合操作消耗20%以上的内存,那么mongodb直接停止操作,并向客户端输出错误消息. Pipeline方式使用db.collection.aggregate()函数进行聚合运算,运算速度较快,操作简单.

【Mongodb教程 第十一课 】MongoDB 聚合

聚合操作过程中的数据记录和计算结果返回.聚合操作分组值从多个文档,并可以执行各种操作,分组数据返回单个结果.在SQL COUNT(*)和group by 相当于MongoDB的聚集. aggregate() 方法 对于在MongoDB中聚集,应该使用aggregate()方法. 语法: aggregate() 方法的基本语法如下 >db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION) 例子: 在集合中,有以下的数据: { _id: ObjectId(

MongoDB聚合操作 (group, aggregate, mapReduce操作)

#MongoDb 聚合方法 group aggrate mapreduce# 1. Group (不支持分片,分布计算) * 语法结构 <pre> db.collection.group({ key:{category:1}, // 根据category来分类 cond:{shop_price:{$gt:20}}, // 附加条件商品借个大于20的商品 reduce:function(curr, result){ // curr 标识一行记录, result自定义变量, }, initial:

mongodb聚合查询

MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*). $sum 计算总和. db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) $avg 计算平均值 db.mycol.aggregate([{$group : {_id : "$by_use

MongoDB 聚合管道(Aggregation Pipeline)

MongoDB 聚合管道(Aggregation Pipeline) - 张善友 时间 2013-12-27 22:40:00            博客园_张善友相似文章 (0)原文                  http://www.cnblogs.com/shanyou/p/3494854.html添加到推刊 收藏到推刊创建推刊 收 藏  取消 已收藏到推刊! 创建推刊 × Modal header --> 请填写推刊名 描述不能大于100个字符! 权限设置: 公开    仅自己可见

Mongodb学习笔记四(Mongodb聚合函数)

第四章 Mongodb聚合函数 插入 测试数据 for(var j=1;j<3;j++){ for(var i=1;i<3;i++){ var person={ Name:"jack"+i, Age:i, Address:["henan","wuhan"], Course:[ {Name:"shuxue",Score:i}, {Name:"wuli",Score:i} ] } db.DemoTe

mongodb MongoDB 聚合 group

MongoDB 聚合 MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*). 基本语法为:db.collection.aggregate( [ <stage1>, <stage2>, ... ] ) 现在在mycol集合中有以下数据: { "_id" : 1, "name" : "tom", "sex" :

mongodb MongoDB 聚合 group(转)

MongoDB 聚合 MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*). 基本语法为:db.collection.aggregate( [ <stage1>, <stage2>, ... ] ) 现在在mycol集合中有以下数据: { "_id" : 1, "name" : "tom", "sex" :

MongoDB 聚合分组取第一条的案例及实现

关键字:MongoDB: aggregate:forEach 今天开发同学向我们提了一个紧急的需求,从集合mt_resources_access_log中,根据字段refererDomain分组,取分组中最近一笔插入的数据,然后将这些符合条件的数据导入到集合mt_resources_access_log_new中. 接到这个需求,还是有些心虚的,原因有二,一是,业务需要,时间紧:二是,实现这个功能MongoDB聚合感觉有些复杂,聚合要走好多步. 数据记录格式如下: 记录1 { "_id"

MongoDB聚合管道

通过上一篇文章中,认识了MongoDB中四个聚合操作,提供基本功能的count.distinct和group,还有可以提供强大功能的mapReduce. 在MongoDB的2.2版本以后,聚合框架中多了一个新的成员,聚合管道,数据进入管道后就会经过一级级的处理,直到输出. 对于数据量不是特别大,逻辑也不是特别复杂的聚合操作,聚合管道还是比mapReduce有很多优势的: 相比mapReduce,聚合管道比较容易理解和使用 可以直接使用管道表达式操作符,省掉了很多自定义js function,一定