文档首页 → 开发应用程序 → Python 驱动程序 → PyMongo
分组和总计
本页内容
简介
在本教程中,您可以通过完成和运行一个示例应用程序来学习如何使用 PyMongo 构建聚合管道,在集合上执行聚合并打印结果。此聚合执行以下操作
通过字段值匹配文档的子集
按常见字段值分组文档
向每个结果文档添加计算字段
聚合任务摘要
本教程演示了如何分组和分析客户订单数据。结果显示了在 2020 年购买商品的客户列表,包括每位客户 2020 年的订单历史。
此示例使用一个集合,orders
,它包含描述单个产品订单的文档。由于每个订单只能对应一个客户,因此订单文档按 customer_id
字段分组,该字段包含客户电子邮件地址。
开始之前
在开始本教程之前,请完成聚合模板应用程序的说明,以设置一个可工作的Python应用程序。
设置应用程序后,通过在应用程序中添加以下代码来访问orders
集合
orders_coll = agg_db["orders"]
删除任何现有数据,并将以下示例数据插入到orders
集合中,如下所示
orders_coll.delete_many({}) order_data = [ { "customer_id": "elise_smith@myemail.com", "orderdate": datetime(2020, 5, 30, 8, 35, 52), "value": 231 }, { "customer_id": "elise_smith@myemail.com", "orderdate": datetime(2020, 1, 13, 9, 32, 7), "value": 99 }, { "customer_id": "oranieri@warmmail.com", "orderdate": datetime(2020, 1, 1, 8, 25, 37), "value": 63 }, { "customer_id": "tj@wheresmyemail.com", "orderdate": datetime(2019, 5, 28, 19, 13, 32), "value": 2 }, { "customer_id": "tj@wheresmyemail.com", "orderdate": datetime(2020, 11, 23, 22, 56, 53), "value": 187 }, { "customer_id": "tj@wheresmyemail.com", "orderdate": datetime(2020, 8, 18, 23, 4, 48), "value": 4 }, { "customer_id": "elise_smith@myemail.com", "orderdate": datetime(2020, 12, 26, 8, 55, 46), "value": 4 }, { "customer_id": "tj@wheresmyemail.com", "orderdate": datetime(2021, 2, 28, 7, 49, 32), "value": 1024 }, { "customer_id": "elise_smith@myemail.com", "orderdate": datetime(2020, 10, 3, 13, 49, 44), "value": 102 } ] orders_coll.insert_many(order_data)
教程
为2020年的订单添加匹配阶段
首先,添加一个$match阶段,以匹配2020年放置的订单
pipeline.append({ "$match": { "orderdate": { "$gte": datetime(2020, 1, 1, 0, 0, 0), "$lt": datetime(2021, 1, 1, 0, 0, 0) } } })
添加一个排序阶段以按订单日期排序
接下来,添加一个$sort阶段,对orderdate
字段进行升序排序,以便在下一阶段中显示每个客户的最早2020年购买
pipeline.append({ "$sort": { "orderdate": 1 } })
添加一个按电子邮件地址分组阶段
添加一个$group阶段,根据customer_id
字段的值对订单进行分组。在此阶段中,添加聚合操作以在结果文档中创建以下字段
first_purchase_date
:客户的首次购买日期total_value
:客户所有购买的总额total_orders
:客户的购买总数orders
:客户所有购买的列表,包括每次购买的日期和金额
pipeline.append({ "$group": { "_id": "$customer_id", "first_purchase_date": {"$first": "$orderdate"}, "total_value": {"$sum": "$value"}, "total_orders": {"$sum": 1}, "orders": {"$push": {"orderdate": "$orderdate", "value": "$value"}} } })
添加一个排序阶段以按首次订单日期排序
接下来,添加另一个$sort阶段,对first_purchase_date
字段进行升序排序
pipeline.append({ "$sort": { "first_purchase_date": 1 } })
添加一个设置阶段以显示电子邮件地址
添加一个$set阶段,从在$group
阶段设置的_id
字段中的值重新创建customer_id
字段
pipeline.append({ "$set": { "customer_id": "$_id" } })
添加一个未设置的阶段以删除不需要的字段
最后,添加一个$unset阶段。$unset阶段会从结果文档中删除_id字段
pipeline.append({"$unset": ["_id"]})
解读结果
聚合返回了2020年客户订单的以下摘要
{ 'first_purchase_date': datetime.datetime(2020, 1, 1, 8, 25, 37), 'total_value': 63, 'total_orders': 1, 'orders': [ { 'orderdate': datetime.datetime(2020, 1, 1, 8, 25, 37), 'value': 63 } ], 'customer_id': 'oranieri@warmmail.com' } { 'first_purchase_date': datetime.datetime(2020, 1, 13, 9, 32, 7), 'total_value': 436, 'total_orders': 4, 'orders': [ { 'orderdate': datetime.datetime(2020, 1, 13, 9, 32, 7), 'value': 99 }, { 'orderdate': datetime.datetime(2020, 5, 30, 8, 35, 52), 'value': 231 }, { 'orderdate': datetime.datetime(2020, 10, 3, 13, 49, 44), 'value': 102 }, { 'orderdate': datetime.datetime(2020, 12, 26, 8, 55, 46), 'value': 4 } ], 'customer_id': 'elise_smith@myemail.com' } { 'first_purchase_date': datetime.datetime(2020, 8, 18, 23, 4, 48), 'total_value': 191, 'total_orders': 2, 'orders': [ { 'orderdate': datetime.datetime(2020, 8, 18, 23, 4, 48), 'value': 4 }, { 'orderdate': datetime.datetime(2020, 11, 23, 22, 56, 53), 'value': 187 } ], 'customer_id': 'tj@wheresmyemail.com' }
结果文档包含了指定客户的所有订单的详细信息,按客户的电子邮件地址分组。
要查看本教程的完整代码,请参阅GitHub上的完成的分组和总计应用程序。