用户登录
用户注册

分享至

mapreduce 聚合

  • 作者: 沉默年代0000
  • 来源: 51数据库
  • 2020-10-04
首先在本地机器上安装并设置MongoDB服务。
从Mongo网站上下载MongoDB,解压到本地目录,比如C:>Mongo
在上一个文件夹内创建数据目录。比如:C:\Mongo\Data
如果数据文件存放在其他地方,那么在用mongod.exe命令启动MongoDB时,需要在命令行加参数—-dbpath
启动服务
MongoDB提供了两种方式:mongod.exe以后台进程启动;mongo.exe启动命令行界面,可做管理操作。这两个可执行文件都位于Mongo\bin目录下;
进入Mongo安装目录的bin目录下,比如:C:> cd Mongo\bin
有两种启动方式,如下:
mongod.exe –dbpath C:\Mongo\data

或者
mongod.exe –config mongodb.config

mongodb.config是Mongo\bin目录下的配置文件,需要在此配置文件中指定数据目录(比如,dbpath= C:\Mongo\Data)的位置。
连接到MongoDB,到这一步,mongo后台服务已经启动,可以通过http://localhost:27017查看。 MongoDB启动运行后,我们接下来看它的聚合函数。
实现聚合函数
在关系数据库中,我们可以在数值型字段上执行包含预定义聚合函数的SQL语句,比如,SUM()、COUNT()、MAX()和MIN()。但是在MongoDB中,需要通过MapReduce功能来实现聚合以及批处理,它跟SQL里用来实现聚合的GROUP BY从句比较类似。下一节将描述关系数据库中SQL方式实现的聚合和相应的通过MongoDB提供的MapReduce实现的聚合。
为了讨论这个主题,我们考虑如下所示的Sales表,它以MongoDB中的反范式形式呈现。
Sales表

#

列名

数据类型

1

OrderId

INTEGER

2

OrderDate

STRING

3

Quantity

INTEGER

4

SalesAmt

DOUBLE

5

Profit

DOUBLE

6

CustomerName

STRING

7

City

STRING

8

State

STRING

9

ZipCode

STRING

10

Region

STRING

11

ProductId

INTEGER

12

ProductCategory

STRING

13

ProductSubCategory

STRING

14

ProductName

STRING

15

ShipDate

STRING

基于SQL和MapReduce的实现
我们提供了一个查询的样例集,这些查询使用聚合函数、过滤条件和分组从句,及其等效的MapReduce实现,即MongoDB实现SQL中GROUP BY的等效方式。在MongoDB存储的文档上执行聚合操作非常有用,这种方式的一个限制是聚合函数(比如,SUM、AVG、MIN、MAX)需要通过mapper和reducer函数来定制化实现。
MongoDB没有原生态的用户自定义函数(UDFs)支持。但是它允许使用db.system.js.save命令来创建并保存JavaScript函数,JavaScript函数可以在MapReduce中复用。下表是一些常用的聚合函数的实现。稍后,我们会讨论这些函数在MapReduce任务中的使用。
聚合函数
Javascript 函数

SUM
db.system.js.save( { _id : "Sum" ,
value : function(key,values)
{
var total = 0;
for(var i = 0; i < values.length;="" i++)="" total="" +="values[i];" return="" total;="" }});="" average="" db.system.js.save(="" {="" _id="" :="" "avg"="" ,="" value="" :="" function(key,values)="" {="" var="" total="Sum(key,values);" var="" mean="total/values.length;" return="" mean;="" }});="" max="" db.system.js.save(="" {="" _id="" :="" "max"="" ,="" value="" :="" function(key,values)="" {="" var="" maxvalue="values[0];" for(var="" i="1;i" min="" db.system.js.save(="" {="" _id="" :="" "min"="" ,="" value="" :="" function(key,values)="" {="" var="" minvalue="values[0];" for(var="" i="1;i" variance="" db.system.js.save(="" {="" _id="" :="" "variance"="" ,="" value="" :="" function(key,values)="" {="" var="" squared_diff="0;" var="" mean="Avg(key,values);" for(var="" i="0;" i="">< values.length;="" i++)="" {="" var="" deviation="values[i]" -="" mean;="" squared_diff="" +="deviation" *="" deviation;="" }="" var="" variance="squared_Diff/(values.length);" return="" variance;="" }});="" std="" deviation="" db.system.js.save(="" {="" _id="" :="" "standard_deviation"="" ,="" value="" :="" function(key,values)="" {="" var="" variance="Variance(key,values);" return="" math.sqrt(variance);="" }});="" sql和mapreduce脚本在四种不同的用例场景中实现聚合函数的代码片段如下表所示。="" 1.各地区的平均订单量="" 下面的查询是用来获取不同地区的平均订单量。="" sql="" query="" mapreduce="" functions="" select="" db.sales.runcommand(="" {="" mapreduce="" :="" "sales"="" ,="" city,="" state,="" region,="" map:function()="" {="" emit="" function="" handles="" the="" group="" by="" emit(="" {="" key="" city:this.city,="" state:this.state,="" region:this.region},="" values="" this.quantity);="" },="" avg(quantity)="" reduce:function(key,values)="" {="" var="" result="Avg(key," values);="" return="" result;="" }="" from="" sales="" group="" by="" city,="" state,="" region="" group="" by="" is="" handled="" by="" the="" emit(keys,="" values)="" line="" in="" the="" map()="" function="" above="" out="" :="" {="" inline="" :="" 1="" }="" });="" 2.产品的分类销售总额="" 下面的查询是用来获取产品的分类销售额,根据产品类别的层级分组。在下面例子中,不同的产品类别作为个体维度,它们也可以被称为更复杂的基于层次的维度。="" sql="" 查询="" mapreduce="" 函数="" select="" db.sales.runcommand(="" {="" mapreduce="" :="" "sales"="" ,="" productcategory,="" productsubcategory,="" productname,="" map:function()="" {="" emit(="" key="" {key0:this.productcategory,="" key1:this.productsubcategory,="" key2:this.productname},="" values="" this.salesamt);="" },="" sum(salesamt)="" reduce:function(key,values)="" {="" var="" result="Sum(key," values);="" return="" result;="" }="" from="" sales="" group="" by="" productcategory,="" productsubcategory,="" productname="" group="" by="" is="" handled="" by="" the="" emit(keys,="" values)="" line="" in="" the="" map()="" function="" above="" out="" :="" {="" inline="" :="" 1="" }="" });="" 3.="" 一种产品的最大利润="" 下面的查询是用来获取一个给定产品基于过滤条件的最大利润。="" sql查询="" mapreduce="" 函数="" select="" db.sales.runcommand(="" {="" mapreduce="" :="" "sales"="" ,="" productid,="" productname,="" map:function()="" {="" if(this.productid="=1)" emit(="" {="" key0:this.productid,="" key1:this.productname},="" this.profit);="" },="" max(salesamt)="" reduce:function(key,values)="" {="" var="" maxvalue="Max(key,values);" return="" maxvalue;="" }="" from="" sales="" where="" productid="’1’" where="" condition="" implementation="" is="" provided="" in="" map()="" function="" group="" by="" productid,="" productname="" group="" by="" is="" handled="" by="" the="" emit(keys,="" values)="" line="" in="" the="" map()="" function="" above="" out="" :="" {="" inline="" :="" 1="" }="" });="" 4.="" 总量、总销售额、平均利润="" 这个场景的需求是计算订单的总数、总销售额和平均利润,订单id在1到10之间,发货时间在2011年的1月1日到12月31日之间。下面的查询是用来执行多个聚合,比如,在指定年份以及指定的不同区域和产品类别范围里订单的总数、总销售额和平均利润。="" sql="" 查询="" mapreduce="" 函数="" select="" db.sales.runcommand(="" {="" mapreduce="" :="" "sales"="" ,="" region,="" productcategory,="" productid,="" map:function()="" {="" emit(="" {="" keys="" region:this.region,="" productcategory:this.productcategory,="" productid:this.productid},="" values="" {quantsum:this.quantity,="" salessum:this.salesamt,="" avgprofit:this.profit}="" );="" }="" sum(quantity),="" sum(sales),="" avg(profit)="" reduce:function(key,values)="" {="" var="" result="{quantSum:0,salesSum:0,avgProfit:0};" var="" count="0;" values.foreach(function(value)="" {="" calculation="" of="" sum(quantity)="" result.quantsum="" +="values[i].quantSum;" calculation="" of="" sum(sales)="" result.salessum="" +="values[i].salesSum;" result.avgprofit="" +="values[i].avgProfit;" count++;="" }="" calculation="" of="" avg(profit)="" result.avgprofit="result.avgProfit" count;="" return="" result;="" },="" from="" sales="" where="" orderid="" between="" 1="" and="" 10="" and="" shipdate="" between="" ‘01/01/2011’="" and="" ‘12/31/2011’="" query="" :="" {="" "orderid"="" :="" {="" "$gt"="" :="" 1="" },="" "orderid"="" :="" {="" "$lt"="" :="" 10="" },="" "shipdate"="" :="" {="" "$gt"="" :="" "01/01/2011"="" },="" "shipdate"="" :="" {="" "$lt"="" :="" "31/12/2011"="" },="" },="" group="" by="" region,="" productcategory,="" productid="" group="" by="" is="" handled="" by="" the="" emit(keys,="" values)="" line="" in="" the="" map()="" function="" above="" limit="" 3;="" limit="" :="" 3,="" out="" :="" {="" inline="" :="" 1="" }="" });="" 既然我们已经看了在不同业务场景下的聚合函数的代码示例,接下来我们准备来测试这些函数。="" 测试聚合函数="" mongodb的mapreduce功能通过数据库命令来调用。map和reduce函数在前面章节里已经使用javascript实现。下面是执行mapreduce函数的语法。="" db.runcommand(="" {="" mapreduce="" :="">,

map : ,

reduce :

[, query : ]

[, sort : ]

[, limit : ]

[, out : ]

[, keeptemp: ]

[, finalize : ]

[, scope : ]

[, jsMode : true]

[, verbose : true]

}

)

Where the Output Options include:

{ replace : "collectionName" }

{ merge : "collectionName"

{ reduce : "collectionName" }

{ inline : 1}
软件
前端设计
程序设计
Java相关