数组表达式运算符主要用于文档中数组的操作,本篇我们主要介绍数组元素的映射及统计:
一、准备工作
初始化学生的学科成绩
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 }