学习MongoDB 九: MongoDB聚合(单一用途的聚合方法)(一)
2016-05-15 22:03
681 查看
聚合指各种可以处理批量记录并返回计算结果的操作,并MongoDB提供了丰富的聚合操作,MongoDB提供了进行聚合的三种方式:聚集管道(Aggregation),Map-Reduce方法,和单一用途的聚合方法。
单一用途的聚合方法:db.collection.count(), db.collection.group(), db.collection.distinct()。
也可以这样获取返回匹配查询结果的数量:
var cursor=db.items.find() 可以以查询只包含索引键的条件, cursor.count()。
我们比较熟悉的group by 的sql语句select key from table group by key,而mongoDB没提供SQL那样通过group By就轻松实现数据库的分组功能, db.collection.group()是对某个字段的对集合进行分组,然后通过聚合每一组中的所有文档,可以对聚合每一组中的所有文档进行处理,来产生最终的我们想要的结果文档。
db.collection.group()使用JavaScript,它受到了一些性能上的限制。大多数情况下,$ group在Aggregation Pipeline提供了一种具有较少的限制适用的替代。可以通过指定的键的集合中的文档和执行简单的聚合函数。
(1)在2.2版本中,返回的数组可以包含最多20000个元素;即最多20000个独特的分组。
(2)聚集管道(Aggregation),Map-Reduce方法都可以运行在分片集合,group()方法不能运行在分片集群中工作。
(3)结果集必须符合最大BSON文档大小(大小为4 MB)。
1.
订单集合记录日期和明细中的数量、产品编码,我们订单集合按照对日期和产品编码进行分组字段,然后对每一组文档进行处理,找出并计算相同的产品的数量。Sql语句:Select pnumber,sum(quantity) as total from orders,items group by pnumber(少了两张表的关联的条件)。
描述:
key:作为分组的key。
reduce:一个聚合函数操作文档的分组操作期间。这些函数可以返回一个sum或count。该函数接受两个参数:当前 文档和这个群体聚集的结果文档。
initial:初始化聚合结果文档变量,为空时自动为每列提供初始变量。
keyf:可选。替代的key 字段。指定一个函数创建一个“key object”作为分组的key。使用keyf而是通过group by领域而不是现有的文档域键组。
cond:过滤条件,根据条件过滤集合的文档。
2、完成器【finalize】
我们对finalize方法 进行详细的介绍,在db.collection.group()返回最终结果之前,每一组文档执行完后,多会触发此方法,此功能可以修改的结果文档或替换的结果文档作为一个整体,执行group()结果集必须符合最大BSON文档大小(大小为4 MB),finalize能对数据传到客户时,进行裁剪结果,可以提高很大的效率。
(1) 我们对订单集合根据日期进行分组,并对相同的产品号数量进行累加,对累加完的产品数量没有大于20 的我们进行删除。减少返回的数据。
(2)每一组文档执行完后,多会触发此方法,此功能可以修改的结果文档,我们对订单的集合实现一天卖出了多少个产品,金额是多少,平均价格是多少。
3.keyf的使用
可以接受一个javascript函数,用来动态的确定分组文档的字段,和key两者必须有一个。我们有时用到比较复杂的key时,可以通过keyf的方法使用javascript函数对要进行分组的字段先进行特殊的处理,然后在做为key进行分组。
我们对订单集合,按照日期的月份进行分组,我们保存的文档的日期是到天,所以我们先转换为月,并计算月份卖出了多少个产品,金额是多少,平均价格是多少。
MongoDB提供了进行聚合的三种方式:聚集管道(Aggregation),Map-Reduce方法,和单一用途的聚合方法,先介绍了单一用途的聚合方法的使用方法,接下去介绍聚集管道(Aggregation)和Map-Reduce方法。
单一用途的聚合方法:db.collection.count(), db.collection.group(), db.collection.distinct()。
一:db.collection.count() 返回匹配查询结果的数量
db.collection.count(query, options) 返回匹配查询结果的数量 相当于mysql的语法:select count(1) from orders where 条件。> db.orders.find() { "_id" : ObjectId("57383f492bd2092c7ed0fec7"), "ino" : "001", "quantity" : 2, " price" : 4 } { "_id" : ObjectId("57383f492bd2092c7ed0fec8"), "ino" : "002", "quantity" : 2, " price" : 6 } { "_id" : ObjectId("57383f492bd2092c7ed0fec9"), "ino" : "003", "quantity" : 3, " price" : 5 } > db.orders.count() 3 > db.orders.count({quantity:{$gt:2}}) 1
也可以这样获取返回匹配查询结果的数量:
var cursor=db.items.find() 可以以查询只包含索引键的条件, cursor.count()。
二: db.collection.distinct() 返回某个字段的非重复值列表
db.collection.distinct(field, query) 返回指定某个字段的非重复的值的列表,结果不能大于最大BSON大小(大小为4 MB) 相当于mysql的语法:select distinct(field) from orders where 条件。> db.orders.find() { "_id" : ObjectId("57383f492bd2092c7ed0fec7"), "ino" : "001", "quantity" : 2, " price" : 4 } { "_id" : ObjectId("57383f492bd2092c7ed0fec8"), "ino" : "002", "quantity" : 2, " price" : 6 } { "_id" : ObjectId("57383f492bd2092c7ed0fec9"), "ino" : "003", "quantity" : 3, " price" : 5 } > db.orders.distinct("quantity") [ 2, 3 ]
三: db.collection.group()
db.collection.group({ key, reduce, initial[, keyf] [, cond] [, finalize] })我们比较熟悉的group by 的sql语句select key from table group by key,而mongoDB没提供SQL那样通过group By就轻松实现数据库的分组功能, db.collection.group()是对某个字段的对集合进行分组,然后通过聚合每一组中的所有文档,可以对聚合每一组中的所有文档进行处理,来产生最终的我们想要的结果文档。
db.collection.group()使用JavaScript,它受到了一些性能上的限制。大多数情况下,$ group在Aggregation Pipeline提供了一种具有较少的限制适用的替代。可以通过指定的键的集合中的文档和执行简单的聚合函数。
(1)在2.2版本中,返回的数组可以包含最多20000个元素;即最多20000个独特的分组。
(2)聚集管道(Aggregation),Map-Reduce方法都可以运行在分片集合,group()方法不能运行在分片集群中工作。
(3)结果集必须符合最大BSON文档大小(大小为4 MB)。
1.
订单集合记录日期和明细中的数量、产品编码,我们订单集合按照对日期和产品编码进行分组字段,然后对每一组文档进行处理,找出并计算相同的产品的数量。Sql语句:Select pnumber,sum(quantity) as total from orders,items group by pnumber(少了两张表的关联的条件)。
> db.orders.find() { "_id" : ObjectId("573848342bd2092c7ed0feca"), "onumber" : "001", "date" : ISOD ate("2014-01-02T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 2, "price" : 5, "pnumber" : "p003" } } { "_id" : ObjectId("573848342bd2092c7ed0fecb"), "onumber" : "002", "date" : ISOD ate("2014-01-03T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 1, "price" : 4, "pnumber" : "p002" } } { "_id" : ObjectId("573848342bd2092c7ed0fecc"), "onumber" : "003", "date" : ISOD ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 10, "price " : 2, "pnumber" : "p001" } } { "_id" : ObjectId("573848342bd2092c7ed0fecd"), "onumber" : "003", "date" : ISOD ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 30, "price " : 4, "pnumber" : "p002" } } { "_id" : ObjectId("573848342bd2092c7ed0fece"), "onumber" : "004", "date" : ISOD ate("2014-01-05T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 5, "price" : 4, "pnumber" : "p002" } } > db.orders.group({ ... key: {'item.pnumber':1}, ... initial : {"total":0}, ... reduce : function Reduce(doc, out) { ... out.total+=doc.item.quantity ... } }); [ { "item.pnumber" : "p003", "total" : 2 }, { "item.pnumber" : "p002", "total" : 36 }, { "item.pnumber" : "p001", "total" : 10 } ]
描述:
key:作为分组的key。
reduce:一个聚合函数操作文档的分组操作期间。这些函数可以返回一个sum或count。该函数接受两个参数:当前 文档和这个群体聚集的结果文档。
initial:初始化聚合结果文档变量,为空时自动为每列提供初始变量。
keyf:可选。替代的key 字段。指定一个函数创建一个“key object”作为分组的key。使用keyf而是通过group by领域而不是现有的文档域键组。
cond:过滤条件,根据条件过滤集合的文档。
2、完成器【finalize】
我们对finalize方法 进行详细的介绍,在db.collection.group()返回最终结果之前,每一组文档执行完后,多会触发此方法,此功能可以修改的结果文档或替换的结果文档作为一个整体,执行group()结果集必须符合最大BSON文档大小(大小为4 MB),finalize能对数据传到客户时,进行裁剪结果,可以提高很大的效率。
(1) 我们对订单集合根据日期进行分组,并对相同的产品号数量进行累加,对累加完的产品数量没有大于20 的我们进行删除。减少返回的数据。
db.orders.group({ key: {date:1}, initial : {"pnumbers":{}}, reduce : function Reduce(doc, out) { if(out.pnumbers[doc.item.pnumber]==null){ out.pnumbers[doc.item.pnumber]=new Object(); out.pnumbers[doc.item.pnumber]=doc.item.quantity; }else{ out.pnumbers[doc.item.pnumber]+=doc.item.quantity; } },finalize : function Finalize(doc) { for(i in doc.pnumbers) { if (doc.pnumbers[i] < 20) { delete doc.pnumbers[i]; } } } }); [ { "date" : ISODate("2014-01-02T16:03:00Z"), "pnumbers" : { } }, { "date" : ISODate("2014-01-03T16:03:00Z"), "pnumbers" : { } }, { "date" : ISODate("2014-01-04T16:03:00Z"), "pnumbers" : { "p002" : 30 } }, { "date" : ISODate("2014-01-05T16:03:00Z"), "pnumbers" : { } } ]
(2)每一组文档执行完后,多会触发此方法,此功能可以修改的结果文档,我们对订单的集合实现一天卖出了多少个产品,金额是多少,平均价格是多少。
db.orders.group({ key: {date:1}, initial :{"total":0,"money":0}, reduce : function Reduce(doc, out) { out.total+=doc.item.quantity; out.money+=doc.item.quantity*doc.item.price; }, finalize : function Finalize(out) { out.avg=out.money/out.total return out; } }); [ { "date" : ISODate("2014-01-02T16:03:00Z"), "total" : 2, "money" : 10, "avg" : 5 }, { "date" : ISODate("2014-01-03T16:03:00Z"), "total" : 1, "money" : 4, "avg" : 4 }, { "date" : ISODate("2014-01-04T16:03:00Z"), "total" : 40, "money" : 140, "avg" : 3.5 }, { "date" : ISODate("2014-01-05T16:03:00Z"), "total" : 5, "money" : 20, "avg" : 4 } ]
3.keyf的使用
可以接受一个javascript函数,用来动态的确定分组文档的字段,和key两者必须有一个。我们有时用到比较复杂的key时,可以通过keyf的方法使用javascript函数对要进行分组的字段先进行特殊的处理,然后在做为key进行分组。
我们对订单集合,按照日期的月份进行分组,我们保存的文档的日期是到天,所以我们先转换为月,并计算月份卖出了多少个产品,金额是多少,平均价格是多少。
> db.orders.find({}) { "_id" : ObjectId("573848342bd2092c7ed0feca"), "onumber" : "001", "date" : ISOD ate("2014-01-02T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 2, "price" : 5, "pnumber" : "p003" } } { "_id" : ObjectId("573848342bd2092c7ed0fecb"), "onumber" : "002", "date" : ISOD ate("2014-01-03T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 1, "price" : 4, "pnumber" : "p002" } } { "_id" : ObjectId("573848342bd2092c7ed0fecc"), "onumber" : "003", "date" : ISOD ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 10, "price " : 2, "pnumber" : "p001" } } { "_id" : ObjectId("573848342bd2092c7ed0fecd"), "onumber" : "003", "date" : ISOD ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 30, "price " : 4, "pnumber" : "p002" } } { "_id" : ObjectId("573848342bd2092c7ed0fece"), "onumber" : "004", "date" : ISOD ate("2014-01-05T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 5, "price" : 4, "pnumber" : "p002" } } > db.orders.group({ ... keyf: function (doc){ ... return{'month':doc.date.getMonth()+1}; ... }, ... initial :{"total":0,"money":0}, ... reduce : function Reduce(doc, out) { ... out.total+=doc.item.quantity; ... out.money+=doc.item.quantity*doc.item.price; ... ... }, ... finalize : function Finalize(out) { ... out.avg=out.money/out.total ... return out; ... } ... }); [ { "month" : 1, "total" : 48, "money" : 174, "avg" : 3.625 } ]
MongoDB提供了进行聚合的三种方式:聚集管道(Aggregation),Map-Reduce方法,和单一用途的聚合方法,先介绍了单一用途的聚合方法的使用方法,接下去介绍聚集管道(Aggregation)和Map-Reduce方法。
相关文章推荐
- mongodb增删改查基本操作
- mongodb创建用户
- MongoDB学习笔记系列:(八) 复制
- MongoDB 3: 使用中的问题,及其应用场景
- MongoDB 3: 使用中的问题,及其应用场景
- mongodb主从复制小结
- MongoDB 2: 安装和使用
- MongoDB 2: 安装和使用
- MongoDB 1: NoSQL 和 SQL的区别
- MongoDB 1: NoSQL 和 SQL的区别
- JSON 的正确用法探讨:Pyhong、MongoDB、JavaScript与Ajax
- MySQL与MongoDB的区别
- centos6.4下安装mongodb-3.2.6
- Mongodb中数据聚合之MapReduce
- 搭建高可用mongodb集群(四)—— 分片
- 搭建高可用mongodb集群(三)—— 深入副本集内部机制
- 搭建高可用mongodb集群(二)—— 副本集
- 搭建高可用mongodb集群(一)——配置mongodb
- MongoDB 安装
- mongodb的使用小结