Node.jsmongoose教程10--聚合(Aggregation)的应用
Posted Sodino
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.jsmongoose教程10--聚合(Aggregation)的应用相关的知识,希望对你有一定的参考价值。
- 1. 聚合操作(Aggregation Operation)
- 2. 聚合管道(Aggregation Pipeline)
- 3. 找出安装了最多应用的手机
- 4. $project
- 5. $size
- 6. $ifNull
- 7. $sort
本文是存储了5个手机数据后再操作的。存储实现见文章:【Node.js】mongoose教程—存储。
GitHub源码链接:sodino#MongoDemo
聚合操作(Aggregation Operation)
官方文档链接:
Aggregation
Aggregation Pipeline Quick Reference
Aggregation Pipeline Operator
Aggregation Commands Comparison
官方是这么描述聚合操作
的:
1 2 3 4 | Aggregations operations process data records and return computed results. Aggregation operations group values from multiple documents together, and can perform a variety of operations on the grouped data to return a single result. |
Sodino勉强翻译一下吧:聚合操作能够处理数据记录并返回处理后的计算结果。聚合操作能够将多个文档记录的值重新划分组别,并在重新分组的数据上执行丰富的计算操作然后返回单一的计算结果。
翻译成大白话就是:聚合操作能够在MongoDB层面进行数据加工、数据挖掘,产生新的有价值的数据记录。
举个例子:
之前的文章mongoose教程07—排重与计数就是聚合操作在实际应用中的例子。
从存储的数据文档中重新计算出了厂商国家数量及符合条件的手机型号数量,这些信息是间接通过已存储的字段加工后挖掘出来的。
MongoDB提供了聚合操作的三种方式:
Aggregation Pipeline
Map-Reduce
Single Purpose Aggregation Operations
三种方式各自的函数名称汇总如下表:
聚合归类 | 函数名称 |
---|---|
Aggregation Pipeline | Model.aggregate() |
Map-Reduce | Model.mapReduce() |
Single Purpose | Model.count() Model.distinct() Model.group() |
上文的排重
和计数
就属于Single Purpose Aggregation Operations,当然还有群组 group()未提及到。
接下来讲一下聚合三种操作中的Aggregation Pipeline及应用场景一例。
聚合管道(Aggregation Pipeline)
MongoDB的聚合框架实现是模仿Data processing pipeline
。数据文档进入多级管道并将文档转换为聚合结果。
聚合管道最基础的功能包括提供类似于查询的过滤器;数据文档转换,能调整聚合结果所输出的文档数据的结构,如在聚合的结果中新增加原始数据文档中没有的字段,如数组长度
、组合名称
等有价值的字段。
还有另外的功能,包括按数据文档的字段进行分组或排序,对数组或成批的数据文档进行再处理,还包括计算平均数、连接/截取字符串等功能。
聚合管道还支持索引等功能。
为了实现以上功能,引入了聚合管道操作符(Aggregation Pipeline Operators)的概念。
操作符分为三类:
- Stage Operators
- Expression Operators
- Accumulators
三类操作符各自分类见下图
找出安装了最多应用的手机
直接以例子来讲聚合管道的应用吧。
在mongoose教程—存储中,存储了5种手机数据,想找出安装了最多应用的手机
数据,该怎么做?
首先,这是要求MongoDB按数组长度进行排序的功能,分解需求:
- 要获取每个apps数组的长度
- 数组长度在聚合结果中要有字段名,即新增字段
- 按新增字段进行排序
- 对apps进行空数据兼容
通过阅读文档,涉及到管道操作符知识点直接列出如下:
$project: 定义查询后的聚合结果,即新增加字段apps_count
,以便排序。
$size: 对数组的长度取值
$ifNull: 空数据兼容
$sort: 排序
下面先直接给出实现代码然后再逐一说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | function findThePhoneWithMostAppsInstalled() Phone.aggregate([$project : apps_count : $size : "$ifNull" : [ "$apps",[]] , device : 1, manufacturer : 1, apps : 1 , $sort: "apps_count" : -1 ]) // .limit(1) // 可加可不加.取结果的phones[0]即可了 .exec((err, phones)=> console.log('---findThePhoneWithMostAppsInstalled()---------------------------------'); if (err) console.log(err); else var phone = phones[0]; console.log(phone); ); |
控制台输出:
$project
$project
能够将数据文档指定的字段传给管道做下一步处理,指定的字段可以是数据文档中原有的字段,也可以是新计算出来的自定义字段。
$project
的原型表达式如下:
1 |
$project: <specifications>
|
其中<specifications>
可以是以下三种形式:
语法 | 描述 |
---|---|
< filed > : < 1 or true> | 指定要包含的字段 |
_id : < 0 or false> | 不处理_id 字段 |
< field >: < expression > | 新增的自定义字段或修改掉原有字段的值 |
所以,在上面的代码中:
1 2 3 4 5 6 7 8 9 10 11 | $project : apps_count : $size : "$ifNull" : [ 如何使用 Node.js Mongoose 删除文档? |