MongoDB高级聚合查询(单用途聚合、聚合管道)

MongoDB提供了多种聚合方式,包括单用途聚合操作如estimatedDocumentCount(), count(), distinct(),以及更复杂的聚合管道。聚合管道允许通过多个阶段处理文档,如$match、$group、$unwind等,实现数据过滤、分组、计算等。在聚合管道中,$match用于筛选文档,$group用于分组和统计,$unwind用于展开数组字段,$project则用于字段的选择和计算。" 103941757,8567429,前端开发:实现完整的评论功能,"['HTML', 'CSS', 'JavaScript', '前端框架', '数据库操作']
摘要由CSDN通过智能技术生成

一、MongoDB聚合

聚合操作处理数据记录并返回计算结果。聚合操作将来自多个文档的值组合在一起,并且可以对分组数据执行各种操作以返回单个结果。MongoDB提供了三种执行聚合的方式:聚合管道,map-reduce函数和单用途聚合方法。
1、单用途聚合操作
MongoDB了提供db.collection.estimatedDocumentCount(), db.collection.count()和db.collection.distinct()。

所有这些操作都聚合来自单个集合的文档。虽然这些操作提供了对公共聚合过程的简单访问,但它们缺乏聚合管道和map-reduce的灵活性和功能。
//图源自官网
(1)db.collection.estimatedDocumentCount()
返回集合或视图中所有文档的计数
示例:检索orders集合中所有文档的计数

> db.orders.find()			//orders集合
{ "_id" : ObjectId("5d3e560d55ad906481cb2ecc"), "cust_id" : "abc123", "status" : "A", "price" : 50, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyy", "qty" : 25, "price" : 1 } ] }
{ "_id" : ObjectId("5d3e570e55ad906481cb2ecd"), "cust_id" : "def456", "status" : "A", "price" : 50, "items" : [ { "sku" : "zzz", "qty" : 25, "price" : 1 }, { "sku" : "www", "qty" : 25, "price" : 1 } ] }
{ "_id" : ObjectId("5d3e573955ad906481cb2ece"), "cust_id" : "ghi789", "status" : "B", "price" : 100, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyy", "qty" : 25, "price" : 1 } ] }
{ "_id" : ObjectId("5d3e587855ad906481cb2ecf"), "cust_id" : "abc123", "status" : "A", "price" : 70, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyy", "qty" : 25, "price" : 1 } ] }

> db.orders.estimatedDocumentCount({})
4

(2)db.collection.count()
返回与find()集合或视图的查询匹配的文档计数 。该 db.collection.count()方法不执行 find()操作,而是计算并返回与查询匹配的结果数。
需要注意的是,在分片群集上,如果存在孤立文档或 正在进行块迁移,则db.collection.count()没有查询谓词可能导致计数 不准确。要避免这些情况,请在分片群集上使用 db.collection.aggregate()方法。
示例:计算orders集合中的所有文档

> db.orders.count()
4

count()等同于 db.collection.find(query).count()构造。以上操作等同于:

> db.orders.find().count()
4

示例:计算与查询匹配的所有文档

> db.orders.count({price : {$gt : 50}})
2
> db.orders.find({price : {$gt : 50}}).count()			//这两个查询等效
2

(3)db.collection.distinct()
在单个集合或视图中查找指定字段的不同值,并在数组中返回结果。
在这里插入图片描述

> db.orders.distinct("cust_id")		//返回不同cust_id的数组
[ "abc123", "def456", "ghi789" ]

> db.orders.distinct("items.sku")		//返回items字段中嵌入字段sku的数组
[ "xxx", "yyy", "www", "zzz" ]

> db.orders.distinct("price",{status : "A"})	//返回status字段为“A”,price字段不同值的数组
[ 50, 70 ]

2、Aggregation Pipeline聚合管道
db.collection.aggregate()是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。

通过这张图,可以了解Aggregate处理的过程:
在这里插入图片描述
在这张图中:
第一阶段:$match阶段按status字段过滤文档,并将那些status等于A的文档传递给下一阶段;

第二阶段:$group阶段按cust_id字段对文档进行分组,以计算每个唯一cust_id的数量总和。

aggregate常用pipeline stage介绍:
(1)$count
返回包含输入到stage的文档的计数,理解为返回与表或视图的find()查询匹配的文档的计数。db.collection.count()方法不执行find()操作,而是计数并返回与查询匹配的结果数。
在这里插入图片描述

> db.orders.find()		//演示集合
{ "_id" : ObjectId("5d3e560d55ad906481cb2ecc"), "cust_id" : "abc123", "status" : "A", "price" : 50, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyy", "qty" : 25, "price" : 1 } ] }
{ "_id" : ObjectId("5d3e570e55ad906481cb2ecd"), "cust_id" : "def456", "status" : "A", "price" : 50, "items" : [ { "sku" : "zzz", "qty" : 25, "price" : 1 }, { "sku" : "www", "qty" : 25, "price" : 1 } ] }
{ "_id" : ObjectId("5d3e573955ad906481cb2ece"), "cust_id" : "ghi789", "status" : "B", "price" : 100, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyy", "qty" : 25, "price" : 1 } ] }
{ "_id" : ObjectId("5d3e587855ad906481cb2ecf"), "cust_id" : "abc123", "status" : "A", "price" : 70, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyy", "qty" : 25, "price" : 1 } ] }

> db.orders.aggregate([
... {$match : {price : {$gt:50}}},	//$match 阶段排除price小于等于50的文档,符合的文档传到下个阶段
... {$count : "High_price"}	//$count阶段返回聚合管道中剩余文档的计数,并将该值分配给名为High_price的字段
... ])
{ "High_price" : 2 }

该$count阶段相当于以下

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值