> 文章列表 > MongoDB 聚合管道中使用数组表达式运算符实现数组元素映射($map)与统计(reduce)

MongoDB 聚合管道中使用数组表达式运算符实现数组元素映射($map)与统计(reduce)

MongoDB 聚合管道中使用数组表达式运算符实现数组元素映射($map)与统计(reduce)

数组表达式运算符主要用于文档中数组的操作,本篇我们主要介绍数组元素的映射及统计:

一、准备工作

初始化学生的学科成绩

db.subjects.insertMany([{ "_id": 1, "name": "张三", "subjects": [ { "name": "英语", "score": 80 }, { "name": "数学", "score": 70 } ] },{ "_id": 2, "name": "李四", "subjects": [ { "name": "英语", "score": 60 }, { "name": "数学", "score": 90 } ] },{ "_id": 3, "name": "王五", "subjects": [ { "name": "英语", "score": 90 }, { "name": "数学", "score": 50 } ] }
])

二、数组元素映射($map)

语法:

{ $map: { input: <expression>, as: <string>, in: <expression> } 
}

在数组的每个元素上执行表达式,并将所有的执行结果组成新数组返回。

其中,

        input: 代表的是输入的数组

        as:可选,代表的是指向数组中元素的变量,如果没有定义,变量名默认是this

        in:数组中元素需要执行的表达式

例子:计算学生的学科成绩是否及格

db.subjects.aggregate([{$project: {"name": 1,"subjects": {$map: {input: "$subjects",as: "subject",in: {$mergeObjects: [ "$$subject",  {"level": {$cond: {if: { $gte: [ "$$subject.score", 60 ] }, then: "及格",else: "不及格"}}}]}}}}
}])

等效于:

db.subjects.aggregate([{$project: {"name": 1,"subjects": {$map: {input: "$subjects",in: {$mergeObjects: [ "$$this",  {"level": {$cond: {if: { $gte: [ "$$this.score", 60 ] }, then: "及格",else: "不及格"}}}]}}}}
}])

聚合查询的结果如下:

{ "_id" : 1, "name" : "张三", "subjects" : [ { "name" : "英语", "score" : 80, "level" : "及格" }, { "name" : "数学", "score" : 70, "level" : "及格" } ] }
{ "_id" : 2, "name" : "李四", "subjects" : [ { "name" : "英语", "score" : 60, "level" : "及格" }, { "name" : "数学", "score" : 90, "level" : "及格" } ] }
{ "_id" : 3, "name" : "王五", "subjects" : [ { "name" : "英语", "score" : 90, "level" : "及格" }, { "name" : "数学", "score" : 50, "level" : "不及格" } ] }

使用变量时,变量前需要加上 "$$"

如果未定义指向数组中元素的变量,则变量名默认是this

三、数组元素统计($reduce)

语法:

{$reduce: {input: <array>,initialValue: <expression>,in: <expression>}
}

在数组的每个元素上执行表达式,并将所有的执行结果合并到一起

其中,

        input:代表的是输入的数组

        initialValue:代表的是合并的结果的初始化值

        in:数组中元素需要执行的表达式,表达式中可以使用的变量包括this和value,其中this代表的是指向数组中元素的变量,value代表的是合并的结果。

例子:计算学生的学科总成绩

db.subjects.aggregate([{$project: {"name": 1,"subjectTotalScore": {$reduce: {input: "$subjects",initialValue: 0,in: { $add: [ "$$value", "$$this.score" ] }}}}}
])

我们对上面的聚合查询语法进行解释:

initialValue: 0

        初始化合并的结果value = 0

in: { $add: [ "$$value", "$$this.score" ] }

        将合并的结果value与当前科目的成绩score相加并赋值给合并的结果value

聚合查询的结果如下:

{ "_id" : 1, "name" : "张三", "subjectTotalScore" : 150 }
{ "_id" : 2, "name" : "李四", "subjectTotalScore" : 150 }
{ "_id" : 3, "name" : "王五", "subjectTotalScore" : 140 }