MongoDB聚合操作

MongoDB聚合框架(Aggregation Framework)是一个计算框架,它可以:

作用在一个或几个集合上;

对集合中的数据进行一系列的运算

将这些数据转化为期望的形式

 

从效果而言,聚合框架相当于sql查询中的:

GROUP BY

LEFT OUTER JOIN

AS等

 

管道(Pipeline)和步骤(Stage)

整个聚合运算过程称为管道(Pipeline),它是由多个步骤(Stage)组成的,

每个管道:

  • 接受一系列文档(原始数据)
  • 每个步骤对这些文档进行一系列运算
  • 结果文档输出给下一个步骤

 

 

聚合运算的基本格式 

pipeline = [$stage1, $stage2, ...stageN]   // 一系列的计算步骤,每个stage是一个json格式

db.<COLLECTION>.aggregate(

  pipeline,

  { options }

);

 

常见步骤

mongo的每个关键词都有一个$符号作为前缀

 

 

常见步骤中的运算符

 

聚合运算的使用场景

聚合查询可以用于OLAP和OLTP场景,例如:

 

 

MQL常用步骤与SQL对比

1. 根据性别查询,跳过100行后,只取20个数据,并对姓名做映射

  

 

 

pipline = [

    {$match:{gender:"男"}},

    {$skip:100},
    {$limit:20},
    {$project:{

      '名':'$first_name',
      '姓':'$last_name'
    }}
    ];

db.user.aggregate(pipline);

  

2.按照部门查找女性员工小于10人的个数

 

pipeline=[

  {$match:{gender:'女'}},

  {$group:{

    _id:'$DEPARTMENT',   // 必须使用_id
    emp_qty:{$sum:1}   //  $sum求和,每次遇到该department就加1
  }},

  {$match:{emp_qty:{$lt:10}}}

];

db.user.aggregate(pipeline);

 

3.mql特有步骤$unwind,把数组展开

db.students.aggregate([{$unwind:'$score'}])

将score数组展开

 

 

4.mql特有步骤$bucket,自动把数值进行分组,放到各个组里

groupBy:按照哪个字段进行分组,

boundaries:指定分桶的范围

output:输出每个分桶的个数

 

 

4.mql特有步骤$bucket,把不同bucket组合起来

 

聚合查询实践

数据模型

{
	"_id" : ObjectId("5dbe7a545368f69de2b4d36e"),
	"street" : "493 Hilll Curve",
	"city" : "Champlinberg",
	"state" : "Texas",
	"country" : "Malaysia",
	"zip" : "24344-1715",
	"phone" : "425.956.7743 x4621",
	"name" : "Destinee Schneider",
	"userId" : 3573,
	"orderDate" : ISODate("2019-03-26T03:20:08.805Z"),
	"status" : "created",
	"shippingFee" : NumberDecimal("8.00"),
	"orderLines" : [
		{
			"product" : "Refined Fresh Tuna",
			"sku" : "2057",
			"qty" : 25,
			"price" : NumberDecimal("56.00"),
			"cost" : NumberDecimal("46.48")
		},
		{
			"product" : "Refined Concrete Ball",
			"sku" : "1738",
			"qty" : 61,
			"price" : NumberDecimal("47.00"),
			"cost" : NumberDecimal("47")
		},
		{
			"product" : "Rustic Granite Towels",
			"sku" : "500",
			"qty" : 62,
			"price" : NumberDecimal("74.00"),
			"cost" : NumberDecimal("62.16")
		},
		{
			"product" : "Refined Rubber Salad",
			"sku" : "1400",
			"qty" : 73,
			"price" : NumberDecimal("93.00"),
			"cost" : NumberDecimal("87.42")
		},
		{
			"product" : "Intelligent Wooden Towels",
			"sku" : "5674",
			"qty" : 72,
			"price" : NumberDecimal("84.00"),
			"cost" : NumberDecimal("68.88")
		},
		{
			"product" : "Refined Steel Bacon",
			"sku" : "5009",
			"qty" : 8,
			"price" : NumberDecimal("53.00"),
			"cost" : NumberDecimal("50.35")
		}
	],
	"total" : NumberDecimal("407")
}

 

总销量

计算到目前为止所有订单的总销售额

 _id 指定要进行分组的字段

result = orders_collection.aggregate([{
    "$group": {
        "_id": 'null',
        "total": {"$sum": "$total"}
    }
}])

 

订单金额汇总

查询2019年第一季度(1月1日~3月31日)已完成订单(completed)的订单总金额和订单总数

from_date = datetime.strptime('2019-01-01', '%Y-%m-%d')
to_date = datetime.strptime('2019-04-01', '%Y-%m-%d')

result1 = orders_collection.aggregate([
    {
        "$match": {
            "status": "completed",
            "orderDate": {
                "$gte": from_date,
                "$lt": to_date
            }
        }
    },
    {
        "$group": {
            "_id": 'null',
            "total": {"$sum": "$total"},
            "shippingFee": {"$sum": "$shippingFee"},
            "count": {"$sum": 1}
        }
    },
    {
        "$project": {
            "grandTotal": {
                "$add": ["$total", "$shippingFee"]
            },
            "count": 1,
            "_id": 0
        }
    }
])

for r in result1:
    print(r)

  

注意在python中不同的操作中的是否需要按照字符串来处理。

当然也可以用mongodb-compass来可视化的编写复杂的聚合条件,并导出为相应编程语言的示例代码。

 

posted @ 2020-04-04 23:42  liekkas01  阅读(398)  评论(0编辑  收藏  举报