算术操作符
abs
返回一个数字的绝对值。
API
db.command.aggregate.abs(<number>)
复制代码
abs
传入的值除数字常量外,也可是任何最终解析成一个数字的表达式。
如果表达式解析为 null
或者指向一个不存在的字段,则 abs
的结果是 null
。如果值解析为 NaN
,则结果是 NaN
。
示例
集合 ratings
有如下记录:
{ _id: 1, start: 5, end: 8 }
复制代码
求得各个记录的 start
和 end
之间的绝对差异大小:
const $ = db.command.aggregate
db.collection('ratings').aggregate()
.project({
delta: $.abs($.subtract(['$start', '$end']))
})
.end()
复制代码
结果:
{ _id : 1, delta : 3 }
复制代码
add
将数字相加或将数字加在日期上。如果数组中的其中一个值是日期,那么其他值将被视为毫秒数加在该日期上。
API
db.command.aggregate.add([<表达式1>, <表达式2>, ...])
复制代码
表达式可以是形如 $ + 指定字段
,能够被解析成字符串即可。
示例
集合 staff
有如下记录:
{ _id: 1, department: "x", sales: 5, engineer: 10, lastUpdate: ISODate("2019-05-01T00:00:00Z") }
{ _id: 2, department: "y", sales: 10, engineer: 20, lastUpdate: ISODate("2019-05-01T02:00:00Z") }
复制代码
数字求和
求得各个记录人数总数:
const $ = db.command.aggregate
db.collection('staff').aggregate()
.project({
department: 1,
total: $.add(['$sales', '$engineer'])
})
.end()
复制代码
结果:
{ _id: 1, department: "x", total: 15 }
{ _id: 2, department: "y", total: 30 }
复制代码
增加日期值
获取各个记录的 lastUpdate
加一个小时之后的值:
const $ = db.command.aggregate
db.collection('staff').aggregate()
.project({
department: 1,
lastUpdate: $.add(['$lastUpdate', 60*60*1000])
})
.end()
复制代码
结果:
{ _id: 1, department: "x", lastUpdate: ISODate("2019-05-01T01:00:00Z") }
{ _id: 2, department: "y", lastUpdate: ISODate("2019-05-01T03:00:00Z") }
复制代码
ceil
向上取整,返回大于或等于给定数字的最小整数。
API
db.command.aggregate.ceil(<number>)
复制代码
<number>
可以是任意解析为数字的表达式。如果表达式解析为 null
或指向一个不存在的字段,则返回 null
,如果解析为 NaN
,则返回 NaN
。
示例
集合 sales
有如下记录:
{ _id: 1, sales: 5.2 }
{ _id: 2, sales: -3.2 }
复制代码
取各个数字的向上取整值:
const $ = db.command.aggregate
db.collection('sales').aggregate()
.project({
sales: $.ceil('$sales')
})
.end()
复制代码
结果:
{ _id: 1, sales: 6 }
{ _id: 2, sales: -3 }
复制代码
divide
传入被除数和除数,求商。
API
db.command.aggregate.divide([<被除数表达式>, <除数表达式>])
复制代码
表达式可以是任意解析为数字的表达式。
示例
集合 railroads
有如下:
{ _id: 1, meters: 5300 }
{ _id: 3, meters: 130 }
复制代码
取各个数字转换为千米之后的值:
const $ = db.command.aggregate
db.collection('railroads').aggregate()
.project({
km: $.divide(['$meters', 1000])
})
.end()
复制代码
结果:
{ _id: 1, km: 5.3 }
{ _id: 3, km: 0.13 }
复制代码
exp
取 e(自然对数的底数,欧拉数) 的 n 次方。
API
db.command.aggregate.exp(<exponent>)
复制代码
<exponent>
可以是任意解析为数字的表达式。如果表达式解析为 null
或指向一个不存在的字段,则返回 null
,如果解析为 NaN
,则返回 NaN
。
示例
集合 math
有如下记录:
{ _id: 1, exp: 0 }
{ _id: 2, exp: 1 }
复制代码
const $ = db.command.aggregate
db.collection('math').aggregate()
.project({
result: $.exp('$exp')
})
.end()
复制代码
结果:
{ _id: 1, result: 1 }
{ _id: 2, result: 2.71828182845905 }
复制代码
floor
向下取整,返回大于或等于给定数字的最小整数。
API
db.command.aggregate.floor(<number>)
复制代码
<number>
可以是任意解析为数字的表达式。如果表达式解析为 null
或指向一个不存在的字段,则返回 null
,如果解析为 NaN
,则返回 NaN
。
示例
集合 sales
有如下记录:
{ _id: 1, sales: 5.2 }
{ _id: 3, sales: -3.2 }
复制代码
取各个数字的向下取整值:
const $ = db.command.aggregate
db.collection('sales').aggregate()
.project({
sales: $.floor('$sales')
})
.end()
复制代码
结果:
{ _id: 1, sales: 5 }
{ _id: 3, sales: -6 }
复制代码
ln
计算给定数字在自然对数值。
API
db.command.aggregate.ln(<number>)
复制代码
<number>
可以是任意解析为非负数字的表达式。
ln
等价于 log([<number>, Math.E])
,其中 Math.E
是 JavaScript
获取 e
的值的方法。
示例
计算给定数字在自然对数值。
db.command.aggregate.ln(<number>)
复制代码
<number>
可以是任意解析为非负数字的表达式。
ln
等价于 log([<number>, Math.E])
,其中 Math.E
是 JavaScript
获取 e
的值的方法。
log
计算给定数字在给定对数底下的 log 值。
API
db.command.aggregate.log([<number>, <base>])
复制代码
<number>
可以是任意解析为非负数字的表达式。<base>
可以是任意解析为大于 1 的数字的表达式。
如果任一参数解析为 null
或指向任意一个不存在的字段,log
返回 null
。如果任一参数解析为 NaN
,log
返回 NaN
。
示例
集合 curve
有如下记录:
{ _id: 1, x: 1 }
{ _id: 2, x: 2 }
复制代码
计算 log2(x)
的值:
const $ = db.command.aggregate
db.collection('staff').aggregate()
.project({
log: $.log(['$x', 2])
})
.end()
复制代码
结果:
{ _id: 1, log: 0 }
{ _id: 2, log: 1 }
复制代码
log10
计算给定数字在对数底为 10 下的 log 值。
API
db.command.aggregate.log(<number>)
复制代码
<number>
可以是任意解析为非负数字的表达式。
log10
等同于 log
方法的第二个参数固定为 10。
mod
取模运算,取数字取模后的值。
API
db.command.aggregate.mod([<dividend>, <divisor>])
复制代码
第一个数字是被除数,第二个数字是除数。参数为任意解析为数字的表达式。
示例
集合 shopping
有如下记录:
{ _id: 1, bags: 3, items: 5 }
{ _id: 2, bags: 2, items: 8 }
复制代码
各记录取 items
除以 bags
的余数(items % bags
):
const $ = db.command.aggregate
db.collection('shopping').aggregate()
.project({
overflow: $.mod(['$items', '$bags'])
})
.end()
复制代码
结果:
{ _id: 1, log: 2 }
{ _id: 2, log: 0 }
复制代码
multiply
取传入的数字参数相乘的结果。
API
db.command.aggregate.multiply([<expression1>, <expression2>, ...])
复制代码
参数为任意解析为数字的表达式。
示例
集合 fruits
有如下记录:
{ "_id": 2,"price": 15, "quantity": 50 }
复制代码
求各个水果的的总价:
const $ = db.command.aggregate
db.collection('fruits').aggregate()
.project({
name: 1,
total: $.multiply(['$price', '$quantity']),
})
.end()
复制代码
结果:
{ "_id": 2, "name": "orange", "total": 750 }
复制代码
pow
求给定基数的指数次幂。
API
db.command.aggregate.pow([<base>, <exponent>])
复制代码
参数为任意解析为数字的表达式。
示例
集合 stats
有如下记录:
{ "_id": 1, "x": 2, "y": 3 }
{ "_id": 2, "x": 5, "y": 7 }
复制代码
求 x
和 y
的平方和:
const $ = db.command.aggregate
db.collection('stats').aggregate()
.project({
sumOfSquares: $.add([$.pow(['$x', 2]), $.pow(['$y', 2])]),
})
.end()
复制代码
结果:
{ "_id": 1, "sumOfSquares": 13 }
{ "_id": 2, "sumOfSquares": 74 }
复制代码
sqrt
求平方根。
API
db.command.aggregate.sqrt([<number>])
复制代码
参数为任意解析为非负数字的表达式。
示例
直角三角形集合 triangle
有如下记录:
{ "_id": 1, "x": 2, "y": 3 }
{ "_id": 2, "x": 5, "y": 7 }
{ "_id": 3, "x": 10, "y": 20 }
复制代码
x
和 y
分别为两直角边,则求斜边长:
const $ = db.command.aggregate
db.collection('triangle').aggregate()
.project({
len: $.sqrt([$.add([$.pow(['$x', 2]), $.pow(['$y', 2])])]),
})
.end()
复制代码
结果:
{ "_id": 1, "len": 3.605551275463989 }
{ "_id": 2, "len": 8.602325267042627 }
{ "_id": 3, "len": 22.360679774997898 }
复制代码
subtract
将两个数字相减然后返回差值,或将两个日期相减然后返回相差的毫秒数,或将一个日期减去一个数字返回结果的日期。
API
db.command.aggregate.subtract([<expression1>, <expression2>])
复制代码
参数为任意解析为数字或日期的表达式。
示例
集合 scores
有如下记录:
{ "_id": 1, "max": 10, "min": 1 }
{ "_id": 2, "max": 7, "min": 5 }
复制代码
求各个记录的 max
和 min
的差值。:
const $ = db.command.aggregate
db.collection('scores').aggregate()
.project({
diff: $.subtract(['$max', '$min'])
})
.end()
复制代码
结果:
{ "_id": 1, "diff": 9 }
{ "_id": 2, "diff": 2 }
复制代码
trunc
将数字截断为整形。
API
db.command.aggregate.trunc(<number>)
复制代码
参数为任意解析为数字的表达式。
示例
集合 scores
有如下记录:
{ "_id": 1, "value": 1.21 }
复制代码
const $ = db.command.aggregate
db.collection('scores').aggregate()
.project({
int: $.trunc('$value')
})
.end()
复制代码
结果:
{ "_id": 1, "value": 1 }
复制代码
数组操作符
arrayElemAt
返回在指定数组下标的元素。
API
db.command.aggregate.arrayElemAt([<array>, <index>])
复制代码
<array>
可以是任意解析为数字的表达式。
<index>
可以是任意解析为整形的表达式。如果是正数,arrayElemAt
返回在 index
位置的元素,如果是负数,arrayElemAt
返回从数组尾部算起的 index
位置的元素。
示例
集合 exams
有如下记录:
{ "_id": 1, "scores": [80, 60, 65, 90] }
{ "_id": 2, "scores": [78] }
复制代码
求各个第一次考试的分数和和最后一次的分数:
const $ = db.command.aggregate
db.collection('exams').aggregate()
.project({
first: $.arraElemAt(['$scores', 0]),
last: $.arraElemAt(['$scores', -1]),
})
.end()
复制代码
结果:
{ "_id": 1, "first": 80, "last": 90 }
{ "_id": 2, "first": 78, "last": 78 }
复制代码
arrayToObject
将一个数组转换为对象。
API
语法可以取两种:
第一种:传入一个二维数组,第二维的数组长度必须为 2,其第一个值为字段名,第二个值为字段值
db.command.aggregate.arrayToObject([
[<key1>, <value1>],
[<key2>, <value2>],
...
])
复制代码
第二种:传入一个对象数组,各个对象必须包含字段 k
和 v
,分别指定字段名和字段值
db.command.aggregate.arrayToObject([
{ "k": <key1>, "v": <value1> },
{ "k": <key2>, "v": <value2> },
...
])
复制代码
传入 arrayToObject
的参数只要可以解析为上述两种表示法之一即可。
示例
集合 shops
有如下记录:
{ "_id": 1, "sales": [ ["max", 100], ["min", 50] ] }
{ "_id": 3, "sales": [ { "k": "max", "v": 50 }, { "k": "min", "v": 30 } ] }
复制代码
求各个第一次考试和最后一次的分数:
const $ = db.command.aggregate
db.collection('shops').aggregate()
.project({
sales: $.arrayToObject('$sales'),
})
.end()
复制代码
返回:
{ "_id": 1, "sales": { "max": 100, "min": 50 } }
{ "_id": 3, "sales": { "max": 50, "min": 30 } }
复制代码
concatArrays
将多个数组拼接成一个数组。
API
db.command.aggregate.arrayToObject([ <array1>, <array2>, ... ])
复制代码
参数为任意解析为数组的表达式。
示例
集合 items
有如下记录:
{ "_id": 1, "fruits": [ "apple" ], "vegetables": [ "carrot" ] }
复制代码
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
list: $.concatArrays(['$fruits', '$vegetables']),
})
.end()
复制代码
结果:
{ "_id": 1, "list": [ "apple", "carrot" ] }
复制代码
filter
根据给定条件返回满足条件的数组的子集。
API
db.command.aggregate.filter({ input: <array>, as: <string>, cond: <expression>})
复制代码
字段 | 说明 |
---|---|
input | 一个可以解析为数组的表达式 |
as | 可选,用于表示数组各个元素的变量,默认为 this |
cond | 一个可以解析为布尔值的表达式,用于判断各个元素是否满足条件,各个元素的名字由 as 参数决定(参数名需加 this) |
参数为任意解析为数组的表达式。
示例
集合 fruits
有如下记录:
{
"_id": 1,
"stock": [
{ "name": "apple", "price": 10 },
{ "name": "orange", "price": 20 }
],
}
复制代码
const _ = db.command
const $ = db.command.aggregate
db.collection('fruits').aggregate()
.project({
stock: $.filter({
input: '$stock',
as: 'item',
cond: $.gte(['$$item.price', 15])
})
})
.end()
复制代码
结果:
{ "_id": 1, "stock": [ { "name": "orange", "price": 20} ] }
复制代码
in
给定一个值和一个数组,如果值在数组中则返回 true
,否则返回 false
。
API
db.command.aggregate.in([<value>, <array>])
复制代码
<value>
可以是任意表达式。
<array>
可以是任意解析为数组的表达式。
示例
集合 shops
有如下记录:
{ "_id": 1, "topsellers": ["bread", "ice cream", "butter"] }
{ "_id": 2, "topsellers": ["ice cream", "cheese", "yagurt"] }
复制代码
标记销量最高的商品包含 ice cream
的记录。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
included: $.in(['ice cream', '$topsellers'])
})
.end()
复制代码
结果:
{ "_id": 1, "included": true }
{ "_id": 2, "included": true }
复制代码
indexOfArray
在数组中找出等于给定值的第一个元素的下标,如果找不到则返回 -1。
API
db.command.aggregate.indexOfArray([ <array expression>, <search expression>, <start>, <end> ])
复制代码
字段 | 类型 | 说明 |
---|---|---|
– | string | 一个可以解析为数组的表达式,如果解析为 null,则 indexOfArray 返回 null |
– | string | 对数据各个元素应用的条件匹配表达式 |
– | integer | 可选,用于指定搜索的开始下标,必须是非负整数 |
– | integer | 可选,用于指定搜索的结束下标,必须是非负整数,指定了时也应指定 ,否则 默认当做 |
参数为任意解析为数组的表达式。
示例
集合 stats
有如下记录:
{
"_id": 1,
"sales": [ 1, 6, 2, 2, 5 ]
}
{
"_id": 2,
"sales": [ 4, 2, 1, 5, 2 ]
}
复制代码
const $ = db.command.aggregate
db.collection('stats').aggregate()
.project({
index: $.indexOfArray(['$sales', 2, 2])
})
.end()
复制代码
结果:
{ "_id": 1, "index": 2 }
{ "_id": 2, "index": 4 }
复制代码
isArray
判断给定表达式是否是数组,返回布尔值。
API
db.command.aggregate.isArray(<expression>)
复制代码
参数为任意表达式。
示例
集合 stats
有如下记录:
{
"_id": 1,
"sales": [ 1.32, 6.93, 2.48, 2.82, 5.74 ]
}
{
"_id": 2,
"sales": [ 2.97, 7.13, 1.58, 6.37, 3.69 ]
}
复制代码
计算总销量,如果 sales
是数字,则求 sales * base
,如果 sales
是数组,则求数组元素之和与 base
的乘积。
const $ = db.command.aggregate
db.collection('stats').aggregate()
.project({
truncated: $.map({
input: '$sales',
as: 'num',
in: $.trunc('$$num'),
})
})
.project({
total: $.sum('$truncated')
})
.end()
复制代码
结果:
{ "_id": 1, "index": 16 }
{ "_id": 2, "index": 19 }
复制代码
map
类似 Array 上的 map
方法。
API
db.command.aggregate.map({
input: <expression>,
as: <string>,
in: <expression>
})
复制代码
字段 | 说明 |
---|---|
input | 一个可以解析为数组的表达式 |
as | 可选,用于表示数组各个元素的变量,默认为 this |
in | 一个可以应用在给定数组的各个元素上的表达式,各个元素的名字由 as 参数决定(参数名需加 this) |
示例
集合 stats
有如下记录:
{
"_id": 1,
"sales": [ 1.32, 6.93, 2.48, 2.82, 5.74 ]
}
{
"_id": 2,
"sales": [ 2.97, 7.13, 1.58, 6.37, 3.69 ]
}
复制代码
将各个数字截断为整形,然后求和
const $ = db.command.aggregate
db.collection('stats').aggregate()
.project({
truncated: $.map({
input: '$sales',
as: 'num',
in: $.trunc('$$num'),
})
})
.project({
total: $.sum('$truncated')
})
.end()
复制代码
结果:
{ "_id": 1, "index": 16 }
{ "_id": 2, "index": 19 }
复制代码
objectToArray
将一个对象转换为数组。方法把对象的每个键值对都变成输出数组的一个元素,元素形如 { k: <key>, v: <value> }
。
API
db.command.aggregate.objectToArray(<object>)
复制代码
示例
集合 items
有如下记录:
{ "_id": 1, "attributes": { "color": "red", "price": 150 } }
{ "_id": 2, "attributes": { "color": "blue", "price": 50 } }
复制代码
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
array: $.objectToArray('$attributes')
})
.end()
复制代码
结果:
{ "_id": 1, "array": [{ "k": "color", "v": "red" }, { "k": "price", "v": 150 }] }
{ "_id": 2, "array": [{ "k": "color", "v": "blue" }, { "k": "price", "v": 50 }] }
复制代码
range
返回一组生成的序列数字。给定开始值、结束值、非零的步长,range
会返回从开始值开始逐步增长、步长为给定步长、但不包括结束值的序列。
API
db.command.aggregate.range([<start>, <end>, <non-zero step>])
复制代码
字段 | 说明 |
---|---|
start | 开始值,一个可以解析为整形的表达式 |
end | 结束值,一个可以解析为整形的表达式 |
non-zero step | 可选,步长,一个可以解析为非零整形的表达式,默认为 1 |
示例
集合 stats
有如下记录:
{ "_id": 1, "max": 52 }
{ "_id": 2, "max": 38 }
复制代码
const $ = db.command.aggregate
db.collection('stats').aggregate()
.project({
points: $.range([0, '$max', 10])
})
.end()
复制代码
结果:
{ "_id": 1, "points": [0, 10, 20, 30, 40, 50] }
{ "_id": 2, "points": [0, 10, 20] }
复制代码
reduce
类似 JavaScript 的 reduce
方法。
API
db.command.aggregate.reduce({
input: <array>
initialValue: <expression>,
in: <expression>
})
复制代码
字段 | 说明 |
---|---|
input | 输入数组,可以是任意解析为数组的表达式 |
initialValue | 初始值 |
in | 用来作用于每个元素的表达式,在 in 中有两个可用变量,value 是表示累计值的变量,this 是表示当前数组元素的变量 |
示例
简易字符串拼接
集合 player
有如下记录:
{ "_id": 1, "fullname": [ "Stephen", "Curry" ] }
复制代码
获取各个球员的全名,并加 Player:
前缀:
const $ = db.command.aggregate
db.collection('player').aggregate()
.project({
info: $.reduce({
input: '$fullname',
initialValue: 'Player:',
in: $.concat(['$$value', ' ', '$$this']),
})
})
.end()
复制代码
返回如下:
{ "_id": 1, "info": "Player: Stephen Curry" }
复制代码
不加前缀:
const $ = db.command.aggregate
db.collection('player').aggregate()
.project({
name: $.reduce({
input: '$fullname',
initialValue: '',
in: $.concat([
'$$value',
$.cond({
if: $.eq(['$$value', '']),
then: '',
else: ' ',
}),
'$$this',
]),
})
})
.end()
复制代码
结果:
{ "_id": 1, "name": "Stephen Curry" }
复制代码
reverseArray
返回给定数组的倒序形式。
API
db.command.aggregate.reverseArray(<array>)
复制代码
参数为任意解析为数组表达式。
示例
集合 stats
有如下记录:
{
"_id": 1,
"sales": [ 1, 2, 3, 4, 5 ]
}
复制代码
取 sales
倒序:
const $ = db.command.aggregate
db.collection('stats').aggregate()
.project({
reversed: $.reverseArray('$sales'),
})
.end()
复制代码
结果:
{ "_id": 1, "reversed": [5, 4, 3, 2, 1] }
复制代码
size
返回数组长度。
API
db.command.aggregate.size(<array>)
复制代码
<array>
可以是任意解析为数组的表达式。
示例
集合 shops
有如下:
{ "_id": 1, "staff": [ "John", "Middleton", "George" ] }
复制代码
计算各个商店的雇员数量:
const $ = db.command.aggregate
db.collection('staff').aggregate()
.project({
totalStaff: $.size('$staff')
})
.end()
复制代码
结果:
{ "_id": 1, "totalStaff": 3 }
复制代码
slice
类似 JavaScritp 的 slice
方法。返回给定数组的指定子集。
API
语法有两种:
返回从开头或结尾开始的 n
个元素:
db.command.aggregate.slice([<array>, <n>])
复制代码
返回从指定位置算作数组开头、再向后或向前的 n
个元素:
db.command.aggregate.slice([<array>, <position>, <n>])
复制代码
<array>
可以是任意解析为数组的表达式。
<position>
可以是任意解析为整形的表达式。如果是正数,则将数组的第 <position>
个元素作为数组开始;如果 <position>
比数组长度更长,slice
返回空数组。如果是负数,则将数组倒数第 <position>
个元素作为数组开始;如果 <position>
的绝对值大于数组长度,则开始位置即为数组开始位置。
<n>
可以是任意解析为整形的表达式。如果 <position>
有提供,则 <n>
必须为正整数。如果是正数,slice
返回前 n
个元素。如果是负数,slice
返回后 n
个元素。
示例
集合 people
有如下记录:
{ "_id": 2, "hobbies": [ "golf", "handball" ] }
复制代码
统一返回前两个爱好:
const $ = db.command.aggregate
db.collection('fruits').aggregate()
.project({
hobbies: $.slice(['$hobbies', 2]),
})
.end()
复制代码
结果:
{ "_id": 2, "hobbies": [ "golf", "handball" ] }
复制代码
zip
把二维数组的第二维数组中的相同序号的元素分别拼装成一个新的数组进而组装成一个新的二维数组。如可将 [ [ 1, 2, 3 ], [ "a", "b", "c" ] ]
转换成 [ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ]
。
API
db.command.aggregate.zip({
inputs: [<array1>, <array2>, ...],
useLongestLength: <boolean>,
defaults: <array>
})
复制代码
inputs
是一个二维数组(inputs
不可以是字段引用),其中每个元素的表达式(这个可以是字段引用)都可以解析为数组。如果其中任意一个表达式返回 null
,<inputs>
也返回 null
。如果其中任意一个表达式不是指向一个合法的字段 / 解析为数组 / 解析为 null
,则返回错误。
useLongestLength
决定输出数组的长度是否采用输入数组中的最长数组的长度。默认为 false
,即输入数组中的最短的数组的长度即是输出数组的各个元素的长度。
defaults
是一个数组,用于指定在输入数组长度不一的情况下时采用的数组各元素默认值。指定这个字段则必须指定 useLongestLength
,否则返回错误。如果 useLongestLength
是 true
但是 defaults
是空或没有指定,则 zip
用 null
做数组元素的缺省默认值。指定各元素默认值时 defaults
数组的长度必须是输入数组最大的长度。
示例
集合 stats
有如下记录:
{ "_id": 1, "zip1": [1, 2], "zip2": [3, 4], "zip3": [5, 6]}
{ "_id": 3, "zip1": [1, 2], "zip2": [3]}
复制代码
只传 inputs
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
zip: $.zip({
inputs: [
'$zip1', // 字段引用
'$zip2',
'$zip3',
],
})
})
.end()
复制代码
结果:
{ "_id": 1, "zip": [ [1, 3, 5], [2, 4, 6] ] }
{ "_id": 3, "zip": null }
复制代码
设置 useLongestLength
如果设 useLongestLength
为 true
:
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
zip: $.zip({
inputs: [
'$zip1', // 字段引用
'$zip2',
'$zip3',
],
useLongestLength: true,
})
})
.end()
复制代码
结果:
{ "_id": 1, "zip": [ [1, 3, 5], [2, 4, 6] ] }
{ "_id": 2, "zip": [ [1, 3, 4], [2, null, 5], [null, null, 6] ] }
复制代码
设置 defaults
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
zip: $.zip({
inputs: [
'$zip1', // 字段引用
'$zip2',
'$zip3',
],
useLongestLength: true,
defaults: [-300, -200, -100],
})
})
.end()
复制代码
结果:
{ "_id": 1, "zip": [ [1, 3, 5], [2, 4, 6] ] }
{ "_id": 2, "zip": [ [1, 3, 4], [2, -200, 5], [-300, -200, 6] ] }
复制代码
布尔操作符
and
给定多个表达式,and
仅在所有表达式都返回 true
时返回 true
,否则返回 false
。
API
db.command.aggregate.and([<expression1>, <expression2>, ...])
复制代码
如果表达式返回 false
、null
、0
、或 undefined
,表达式会解析为 false
,否则对其他返回值都认为是 true
。
示例
集合 price
有如下记录:
{ "_id": 1, "min": 10, "max": 100 }
复制代码
求 min
大于等于 30 且 max
小于等于 80 。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
fullfilled: $.and([$.gte(['$min', 30]), $.lte(['$max', 80])])
})
.end()
复制代码
结果:
{ "_id": 1, "fullfilled": false }
复制代码
not
给定一个表达式,如果表达式返回 true
,则 not
返回 false
,否则返回 true
。注意表达式不能为逻辑表达式(and
、or
、nor
、not
)。
API
db.command.aggregate.not(<expression>)
复制代码
如果表达式返回 false
、null
、0
、或 undefined
,表达式会解析为 false
,否则对其他返回值都认为是 true
。
示例
集合 price
有如下:
{ "_id": 1, "min": 10, "max": 100 }
复制代码
求 min
不大于 40 。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
fullfilled: $.not($.gt(['$min', 40]))
})
.end()
复制代码
结果:
{ "_id": 1, "fullfilled": true }
复制代码
or
给定多个表达式,如果任意一个表达式返回 true
,则 or
返回 true
,否则返回 false
。
API
db.command.aggregate.or([<expression1>, <expression2>, ...])
复制代码
如果表达式返回 false
、null
、0
、或 undefined
,表达式会解析为 false
,否则对其他返回值都认为是 true
。
示例
集合 price
有如下:
{ "_id": 2, "min": 60, "max": 80 }
{ "_id": 3, "min": 30, "max": 50 }
复制代码
求 min
小于 40 且 max
大于 60 的。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
fullfilled: $.or([$.lt(['$min', 30]), $.gt(['$max', 60])])
})
.end()
复制代码
结果:
{ "_id": 2, "fullfilled": false }
{ "_id": 3, "fullfilled": true }
复制代码
比较操作符
cmp
给定两个值,返回其比较值:
API
如果第一个值小于第二个值,返回 -1如果第一个值大于第二个值,返回 1如果两个值相等,返回 0
db.command.aggregate.cmp([<expression1>, <expression2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "shop1": 10, "shop2": 100 }
{ "_id": 2, "shop1": 80, "shop2": 20 }
{ "_id": 3, "shop1": 50, "shop2": 50 }
复制代码
求 shop1
和 shop2
的各个物品价格对比。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
compare: $.cmp(['$shop1', '$shop2']))
})
.end()
复制代码
结果:
{ "_id": 1, "compare": -1 }
{ "_id": 2, "compare": 1 }
{ "_id": 3, "compare": 0 }
复制代码
eq
匹配两个值,如果相等则返回 true
,否则返回 false
。
API
db.command.aggregate.eq([<value1>, <value2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "value": 10 }
{ "_id": 2, "value": 80 }
{ "_id": 3, "value": 50 }
复制代码
求 value
等于 50 的记录。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
matched: $.eq(['$value', 50])
})
.end()
复制代码
结果:
{ "_id": 1, "matched": false }
{ "_id": 2, "matched": false }
{ "_id": 3, "matched": true }
复制代码
gt
匹配两个值,如果前者大于后者则返回 true
,否则返回 false
。
API
db.command.aggregate.gt([<value1>, <value2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "value": 10 }
{ "_id": 2, "value": 80 }
复制代码
判断 value
是否大于 50。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
matched: $.gt(['$value', 50])
})
.end()
复制代码
结果:
{ "_id": 1, "matched": false }
{ "_id": 2, "matched": true }
复制代码
gte
匹配两个值,如果前者大于或等于后者则返回 true
,否则返回 false
。
API
db.command.aggregate.gte([<value1>, <value2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "value": 10 }
{ "_id": 2, "value": 80 }
{ "_id": 3, "value": 50 }
复制代码
判断 value
是否大于或等于 50。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
matched: $.gte(['$value', 50])
})
.end()
复制代码
结果:
{ "_id": 1, "matched": false }
{ "_id": 2, "matched": true }
{ "_id": 3, "matched": true }
复制代码
lt
匹配两个值,如果前者小于后者则返回 true
,否则返回 false
。
API
db.command.aggregate.lt([<value1>, <value2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "value": 10 }
{ "_id": 2, "value": 80 }
{ "_id": 3, "value": 50 }
复制代码
判断 value
是否小于 50。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
matched: $.lt(['$value', 50])
})
.end()
复制代码
结果:
{ "_id": 1, "matched": true }
{ "_id": 2, "matched": false }
{ "_id": 3, "matched": false }
复制代码
lte
匹配两个值,如果前者小于或等于后者则返回 true
,否则返回 false
。
API
db.command.aggregate.lte([<value1>, <value2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "value": 10 }
{ "_id": 2, "value": 80 }
{ "_id": 3, "value": 50 }
复制代码
判断 value
是否小于 50。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
matched: $.lte(['$value', 50])
})
.end()
复制代码
结果:
{ "_id": 1, "matched": true }
{ "_id": 2, "matched": false }
{ "_id": 3, "matched": true }
复制代码
neq
匹配两个值,如果不相等则返回 true
,否则返回 false
。
API
db.command.aggregate.neq([<value1>, <value2>])
复制代码
示例
集合 price
有如下记录:
{ "_id": 1, "value": 10 }
{ "_id": 2, "value": 80 }
{ "_id": 3, "value": 50 }
复制代码
求 value
不等于 50 的记录。
const $ = db.command.aggregate
db.collection('price').aggregate()
.project({
matched: $.neq(['$value', 50])
})
.end()
复制代码
结果:
{ "_id": 1, "matched": true }
{ "_id": 2, "matched": true }
{ "_id": 3, "matched": false }
复制代码
条件操作符
cond
计算布尔表达式,返回指定的两个值其中之一。
API
cond
的使用形式如下:
cond({ if: <布尔表达式>, then: <真值>, else: <假值> })
cond([ <布尔表达式>, <真值>, <假值> ])
复制代码
两种形式中,三个参数(if
、then
、else
)都是必须的。
如果布尔表达式为真,那么 $cond
将会返回 <真值>
,否则会返回 <假值>
示例
集合 items
的记录如下:
{ "_id": "0", "name": "item-a", "amount": 100 }
{ "_id": "1", "name": "item-b", "amount": 200 }
{ "_id": "2", "name": "item-c", "amount": 300 }
复制代码
可以使用 cond
,根据 amount
字段,来生成新的字段 discount
:
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
name: 1,
discount: $.cond({
if: $.gte(['$amount', 200]),
then: 0.7,
else: 0.9
})
})
.end()
复制代码
结果:
{ "_id": "0", "name": "item-a", "discount": 0.9 }
{ "_id": "1", "name": "item-b", "discount": 0.7 }
{ "_id": "2", "name": "item-c", "discount": 0.7 }
复制代码
ifNull
计算给定的表达式,如果表达式结果为 null、undefined 或者不存在,那么返回一个替代值;否则返回原值。
API
ifNull([ <表达式>, <替代值> ])
复制代码
示例
集合 items
的记录如下:
{ "_id": "0", "name": "A", "description": "这是商品A" }
{ "_id": "1", "name": "B", "description": null }
{ "_id": "2", "name": "C" }
复制代码
可以使用 ifNull
,对不存在 desc
字段的文档,或者 desc
字段为 null
的文档,补充一个替代值。
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
_id: 0,
name: 1,
description: $.ifNull(['$description', '商品描述空缺'])
})
.end()
复制代码
结果:
{ "name": "A", "description": "这是商品A" }
{ "name": "B", "description": "商品描述空缺" }
{ "name": "C", "description": "商品描述空缺" }
复制代码
switch
根据给定的 switch-case-default
计算返回值、
API
switch({
branches: [
case: <表达式>, then: <表达式>,
case: <表达式>, then: <表达式>,
...
],
default: <表达式>
})
复制代码
示例
集合 items
的记录如下:
{ "_id": "0", "name": "item-a", "amount": 100 }
{ "_id": "1", "name": "item-b", "amount": 200 }
{ "_id": "2", "name": "item-c", "amount": 300 }
复制代码
可以使用 switch
,根据 amount
字段,来生成新的字段 discount
:
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
name: 1,
discount: $.switch({
branches: [
{ case: $.gt(['$amount', 250]), then: 0.8 },
{ case: $.gt(['$amount', 150]), then: 0.9 }
],
default: 1
})
})
.end()
复制代码
结果:
{ "_id": "0", "name": "item-a", "discount": 1 }
{ "_id": "1", "name": "item-b", "discount": 0.9 }
{ "_id": "2", "name": "item-c", "discount": 0.8 }
复制代码
日期操作符
dateFromParts
给定日期的相关信息,构建并返回一个日期对象。
API
db.command.aggregate.dateFromParts({
year: <year>,
month: <month>,
day: <day>,
hour: <hour>,
minute: <minute>,
second: <second>,
millisecond: <ms>,
timezone: <tzExpression>
})
复制代码
你也可以使用 ISO 8601 的标准:
db.command.aggregate.dateFromParts({
isoWeekYear: <year>,
isoWeek: <week>,
isoDayOfWeek: <day>,
hour: <hour>,
minute: <minute>,
second: <second>,
millisecond: <ms>,
timezone: <tzExpression>
})
复制代码
说明
timezone
字段请参考Olson Timezone Identifier,形式类似:Asia/Shanghai
示例
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
date: $.dateFromParts({
year: 2017,
month: 2,
day: 8,
hour: 12,
timezone: 'America/New_York'
}),
})
.end()
复制代码
结果:
{
"date": ISODate("2017-02-08T17:00:00.000Z")
}
复制代码
dateFromString
将一个日期/时间字符串转换为日期对象
API
db.command.aggregate.dateFromString({
dateString: <dateStringExpression>,
timezone: <tzExpression>
})
复制代码
示例
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
date: $.dateFromString({
dateString: "2019-05-14T09:38:51.686Z"
})
})
.end()
复制代码
结果:
{
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
dateToString
根据指定的表达式将日期对象格式化为符合要求的字符串。
API
db.command.aggregate.dateToString({
date: <日期表达式>,
format: <格式化表达式>,
timezone: <时区表达式>,
onNull: <空值表达式>
})
复制代码
下面是四种表达式的详细说明:
名称 | 描述 |
---|---|
日期表达式 | 必选。指定字段值应该是能转化为字符串的日期。 |
格式化表达式 | 可选。它可以是任何包含“格式说明符”的有效字符串。 |
时区表达式 | 可选。指明运算结果的时区。它可以解析格式为 UTC Offset 或者 Olson Timezone Identifier 的字符串。 |
空值表达式 | 可选。当 <日期表达式> 返回空或者不存在的时候,会返回此表达式指明的值。 |
下面是格式说明符的详细说明:
说明符 | 描述 | 合法值 |
---|---|---|
%d | 月份的日期(2位数,0填充) | 01 – 31 |
%G | ISO 8601 格式的年份 | 0000 – 9999 |
%H | 小时(2位数,0填充,24小时制) | 00 – 23 |
%j | 一年中的一天(3位数,0填充) | 001 – 366 |
%L | 毫秒(3位数,0填充) | 000 – 999 |
%m | 月份(2位数,0填充) | 01 – 12 |
%M | 分钟(2位数,0填充) | 00 – 59 |
%S | 秒(2位数,0填充) | 00 – 60 |
%w | 星期几 | 1 – 7 |
%u | ISO 8601 格式的星期几 | 1 – 7 |
%U | 一年中的一周(2位数,0填充) | 00 – 53 |
%V | ISO 8601 格式的一年中的一周 | 1 – 53 |
%Y | 年份(4位数,0填充) | 0000 – 9999 |
%z | 与 UTC 的时区偏移量 | +/-[hh][mm] |
%Z | 以分钟为单位,与 UTC 的时区偏移量 | +/-mmm |
%% | 百分号作为字符 | % |
示例
集合 students
有如下记录:
{ "date": "1999-12-11T16:00:00.000Z", "firstName": "Yuanxin", "lastName": "Dong" }
复制代码
格式化日期
下面是将 date
字段的值,格式化成形如 年-月-日
的字符串:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
formatDate: $.dateToString({
date: '$date',
format: '%Y-%m-%d'
})
})
.end()
复制代码
返回的结果:
{ "formatDate": "1999-12-11" }
复制代码
时区时间
下面是将 date
字段值格式化为上海时区时间的例子:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
formatDate: $.dateToString({
date: '$date',
format: '%H:%M:%S',
timezone: 'Asia/Shanghai'
})
})
.end()
复制代码
结果:
{ "formatDate": "00:00:00" }
复制代码
缺失情况的默认值
当指定的 <日期表达式>
返回空或者不存在的时候,可设默认值:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
formatDate: $.dateToString({
date: '$empty',
onNull: 'null'
})
})
.end()
复制代码
结果:
{ "formatDate": "null" }
复制代码
dayOfMonth
返回日期字段对应的天数(一个月中的哪一天),是一个介于 1 至 31 之间的数字。
API
db.command.aggregate.dayOfMonth(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 dayOfMonth()
对 date
字段进行投影,获取对应的日期:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
dayOfMonth: $.dayOfMonth('$date')
})
.end()
复制代码
结果:
{
"dayOfMonth": 14
}
复制代码
dayOfWeek
返回日期字段对应的天数(一周中的第几天),是一个介于 1(周日)到 7(周六)之间的整数。
API
注意:周日是每周的第 1 天*
db.command.aggregate.dayOfWeek(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 dayOfWeek()
对 date
字段进行投影,获取对应的天数(一周中的第几天):
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
dayOfWeek: $.dayOfWeek('$date')
})
.end()
复制代码
结果:
{
"dayOfWeek": 3
}
复制代码
dayOfYear
返回日期字段对应的天数(一年中的第几天),是一个介于 1 到 366 之间的整数。
API
db.command.aggregate.dayOfYear(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 dayOfYear()
对 date
字段进行投影,获取对应的天数(一年中的第几天):
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
dayOfYear: $.dayOfYear('$date')
})
.end()
复制代码
结果:
{
"dayOfYear": 134
}
复制代码
hour
返回日期字段对应的小时数,是一个介于 0 到 23 之间的整数。
API
db.command.aggregate.hour(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 hour()
对 date
字段进行投影,获取对应的小时数:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
hour: $.hour('$date')
})
.end()
复制代码
结果:
{
"hour": 9
}
复制代码
isoDayOfWeek
返回日期字段对应的 ISO 8601 标准的天数(一周中的第几天),是一个介于 1(周一)到 7(周日)之间的整数。
API
db.command.aggregate.month(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 month()
对 date
字段进行投影,获取对应的 ISO 8601 标准的天数(一周中的第几天):
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
isoDayOfWeek: $.isoDayOfWeek('$date')
})
.end()
复制代码
结果:
{
"isoDayOfWeek": 2
}
复制代码
isoWeek
返回日期字段对应的 ISO 8601 标准的周数(一年中的第几周),是一个介于 1 到 53 之间的整数。
API
根据 ISO 8601 标准,周一到周日视为一周,本年度第一个周四所在的那周,视为本年度的第 1 周。
例如:2016 年 1 月 7 日是那年的第一个周四,那么 2016.01.04(周一)到 2016.01.10(周日) 即为第 1 周。同理,2016 年 1 月 1 日的周数为 53。
db.command.aggregate.isoWeek(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 isoWeek()
对 date
字段进行投影,获取对应的 ISO 8601 标准的周数(一年中的第几周):
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
isoWeek: $.isoWeek('$date')
})
.end()
复制代码
结果:
{
"isoWeek": 20
}
复制代码
isoWeekYear
返回日期字段对应的 ISO 8601 标准的天数(一年中的第几天)。
API
此处的“年”以第一周的周一为开始,以最后一周的周日为结束。
db.command.aggregate.isoWeekYear(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 isoWeekYear()
对 date
字段进行投影,获取对应的 ISO 8601 标准的天数(一年中的第几天):
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
isoWeekYear: $.isoWeekYear('$date')
})
.end()
复制代码
结果:
{
"isoWeekYear": 2019
}
复制代码
millisecond
返回日期字段对应的毫秒数,是一个介于 0 到 999 之间的整数。
API
db.command.aggregate.millisecond(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 millisecond()
对 date
字段进行投影,获取对应毫秒数:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
millisecond: $.millisecond('$date'),
})
.end()
复制代码
结果:
{
"millisecond": 686
}
复制代码
minute
返回日期字段对应的分钟数,是一个介于 0 到 59 之间的整数。
API
db.command.aggregate.minute(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 minute()
对 date
字段进行投影,获取对应的分钟数:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
minute: $.minute('$date')
})
.end()
复制代码
结果:
{
"minute": 38
}
复制代码
month
返回日期字段对应的月份,是一个介于 1 到 12 之间的整数。
API
db.command.aggregate.month(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 month()
对 date
字段进行投影,获取对应的月份:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
month: $.month('$date')
})
.end()
复制代码
结果:
{
"month": 5
}
复制代码
second
返回日期字段对应的秒数,是一个介于 0 到 59 之间的整数,在特殊情况下(闰秒)可能等于 60。
API
db.command.aggregate.second(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 second()
对 date
字段进行投影,获取对应的秒数:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
second: $.second('$date')
})
.end()
复制代码
结果:
{
"second": 51
}
复制代码
week
返回日期字段对应的周数(一年中的第几周),是一个介于 0 到 53 之间的整数。
API
每周以周日为开头,每年的第一个周日即为 week 1
的开始,这天之前是 week 0
。
db.command.aggregate.week(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 week()
对 date
字段进行投影,获取对一年中的第几周:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
week: $.week('$date')
})
.end()
复制代码
结果:
{
"week": 19
}
复制代码
year
返回日期字段对应的年份。
API
db.command.aggregate.year(<日期字段>)
复制代码
示例
集合 dates
有以下文档:
{
"_id": 1,
"date": ISODate("2019-05-14T09:38:51.686Z")
}
复制代码
使用 year()
对 date
字段进行投影,获取对应年份:
const $ = db.command.aggregate
db
.collection('dates')
.aggregate()
.project({
_id: 0,
year: $.year('$date')
})
.end()
复制代码
结果:
{
"year": 2019
}
复制代码
subtract
常量操作符
literal
直接返回一个值的字面量,不经过任何解析和处理。
API
literal(<值>)
复制代码
如果 <值>
是一个表达式,那么 literal
不会解析或者计算这个表达式,而是直接返回这个表达式。
示例
比如有一个 items
集合,其中数据如下:
{ "_id": "0", "price": "$1" }
{ "_id": "1", "price": "$5.60" }
复制代码
以字面量的形式使用 $
下面的代码使用 literal
,生成了一个新的字段 isOneDollar
,表示 price
字段是否严格等于 "$1"
。
注意:这里无法使用 eq(['$price', '$1'])
,因为 "$1"
是一个表达式,代表 "1"
字段对应的值,而不是字符串字面量 "$1"
。
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
isOneDollar: $.eq(['$price', $.literal('$1')])
})
.end()
复制代码
结果:
{ "_id": "0", "isOneDollar": true }
{ "_id": "1", "isOneDollar": false }
复制代码
投影一个字段,对应的值为 1
下面的代码使用 literal
,投影了一个新的字段 amount
,其值为 1
。
const $ = db.command.aggregate
db.collection('items').aggregate()
.project({
price: 1,
amount: $.literal(1)
})
.end()
复制代码
结果:
{ "_id": "0", "price": "$1", "amount": 1 }
{ "_id": "1", "price": "$5.60", "amount": 1 }
复制代码
对象操作符
mergeObjects
将多个文档合并为单个文档。
API
使用形式如下:在 group()
中使用时:
mergeObjects(<document>)
复制代码
在其它表达式中使用时:
mergeObjects([<document1>, <document2>, ...])
复制代码
示例
搭配 group()
使用
集合 sales
存在以下文档:
{ "_id": 1, "year": 2018, "name": "A", "volume": { "2018Q1": 500, "2018Q2": 500 } }
{ "_id": 2, "year": 2017, "name": "A", "volume": { "2017Q1": 400, "2017Q2": 300, "2017Q3": 0, "2017Q4": 0 } }
{ "_id": 3, "year": 2018, "name": "B", "volume": { "2018Q1": 100 } }
{ "_id": 4, "year": 2017, "name": "B", "volume": { "2017Q3": 100, "2017Q4": 250 } }
复制代码
下面的代码使用 mergeObjects()
,将用相同 name
的文档合并:
const $ = db.command.aggregate
db.collection('sales').aggregate()
.group({
_id: '$name',
mergedVolume: $.mergeObjects('$volume')
})
.end()
复制代码
结果:
{ "_id": "A", "mergedVolume": { "2017Q1": 400, "2017Q2": 300, "2017Q3": 0, "2017Q4": 0, "2018Q1": 500, "2018Q2": 500 } }
{ "_id": "B", "mergedVolume": { "2017Q3": 100, "2017Q4": 250, "2018Q1": 100 } }
复制代码
一般用法
集合 test
存在以下文档:
{ "_id": 1, "foo": { "a": 1 }, "bar": { "b": 2 } }
{ "_id": 2, "foo": { "c": 1 }, "bar": { "d": 2 } }
{ "_id": 3, "foo": { "e": 1 }, "bar": { "f": 2 } }
复制代码
下面的代码使用 mergeObjects()
,将文档中的 foo
和 bar
字段合并为 foobar
:
const $ = db.command.aggregate
db.collection('sales').aggregate()
.project({
foobar: $.mergeObjects(['$foo', '$bar'])
})
.end()
复制代码
结果:
{ "_id": 1, "foobar": { "a": 1, "b": 2 } }
{ "_id": 2, "foobar": { "c": 1, "d": 2 } }
{ "_id": 3, "foobar": { "e": 1, "f": 2 } }
复制代码
objectToArray
集合操作符
allElementsTrue
输入一个数组,或者数组字段的表达式。如果数组中所有元素均为真值,那么返回 true
,否则返回 false
。空数组永远返回 true
。
API
allElementsTrue([<expression>])
复制代码
示例
集合 test
有如下记录:
{ "_id": 1, "array": [ true ] }
{ "_id": 2, "array": [ ] }
{ "_id": 3, "array": [ false ] }
{ "_id": 4, "array": [ true, false ] }
{ "_id": 5, "array": [ 0 ] }
{ "_id": 6, "array": [ "stark" ] }
复制代码
下面的代码使用 allElementsTrue()
,判断 array
字段中是否均为真值:
const $ = db.command.aggregate
db.collection('price')
.aggregate()
.project({
isAllTrue: $.allElementsTrue(['$array'])
})
.end()
复制代码
结果:
{ "_id": 1, "isAllTrue": true }
{ "_id": 2, "isAllTrue": true }
{ "_id": 3, "isAllTrue": false }
{ "_id": 4, "isAllTrue": false }
{ "_id": 5, "isAllTrue": false }
{ "_id": 6, "isAllTrue": true }
复制代码
setDifference
聚合操作符,输入两个集合,输出只存在于第一个集合中的元素。
API
setDifference([<expression1>, <expression2>])
复制代码
示例
集合 test
存在以下数据:
{ "_id": 1, "A": [ 1, 2 ], "B": [ 1, 2 ] }
{ "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] }
{ "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] }
{ "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] }
{ "_id": 5, "A": [ 1, 2 ], "B": [ ] }
{ "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] }
{ "_id": 7, "A": [ ], "B": [ ] }
{ "_id": 8, "A": [ ], "B": [ 1 ] }
复制代码
下面的代码使用 setDifference
,找到只存在于 B
中的数字:
db.collection('test')
.aggregate()
.project({
isBOnly: $.setDifference(['$B', '$A'])
})
.end()
复制代码
{ "_id": 1, "isBOnly": [] }
{ "_id": 2, "isBOnly": [3] }
{ "_id": 3, "isBOnly": [3] }
{ "_id": 4, "isBOnly": [5] }
{ "_id": 5, "isBOnly": [] }
{ "_id": 6, "isBOnly": [{}, []] }
{ "_id": 7, "isBOnly": [] }
{ "_id": 8, "isBOnly": [1] }
复制代码
setIntersection
聚合操作符,输入两个集合,输出两个集合的交集。
API
setIntersection([<expression1>, <expression2>])
复制代码
示例
集合 test
存在以下数据:
{ "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] }
{ "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] }
{ "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] }
复制代码
下面的代码使用 setIntersection
,输出两个集合的交集:
db.collection('test')
.aggregate()
.project({
commonToBoth: $.setIntersection(['$A', '$B'])
})
.end()
复制代码
结果:
{ "_id": 2, "commonToBoth": [ 1, 2 ] }
{ "_id": 3, "commonToBoth": [ 1, 2 ] }
{ "_id": 4, "commonToBoth": [ 1 ] }
复制代码
setIsSubset
聚合操作符,输入两个集合,判断第一个集合是否是第二个集合的子集。
API
setIsSubset([<expression1>, <expression2>])
复制代码
示例
集合 test
存在以下数据:
{ "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] }
{ "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] }
{ "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] }
复制代码
下面的代码使用 setIsSubset
,判断第一个集合是否是第二个集合的子集:
db.collection('test')
.aggregate()
.project({
AisSubsetOfB: $.setIsSubset(['$A', '$B'])
})
.end()
复制代码
{ "_id": 2, "AisSubsetOfB": true }
{ "_id": 3, "AisSubsetOfB": true }
{ "_id": 4, "AisSubsetOfB": false }
复制代码
setUnion
聚合操作符,输入两个集合,输出两个集合的并集。
API
setUnion([<expression1>, <expression2>])
复制代码
示例
集合 test
存在以下数据:
{ "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] }
{ "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] }
{ "_id": 7, "A": [ ], "B": [ ] }
{ "_id": 8, "A": [ ], "B": [ 1 ] }
复制代码
下面的代码使用 setUnion
,输出两个集合的并集:
db.collection('test')
.aggregate()
.project({
AB: $.setUnion(['$A', '$B'])
})
.end()
复制代码
结果:
{ "_id": 1, "AB": [ 1, 2 ] }
{ "_id": 2, "AB": [ 1, 2 ] }
{ "_id": 6, "AB": [ 1, 2, {}, [] ] }
{ "_id": 7, "AB": [ ] }
{ "_id": 8, "AB": [ 1 ] }
复制代码
字符串操作符
concat
连接字符串,返回拼接后的字符串。
API
db.command.aggregate.concat([<表达式1>, <表达式2>, ...])
复制代码
表达式可以是形如 $ + 指定字段
,也可以是普通字符串。只要能够被解析成字符串即可。
示例
集合 students
的记录如下:
{ "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 }
复制代码
借助 concat
可以拼接 lastName
和 firstName
字段,得到每位学生的名字全称:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
fullName: $.concat(['$firstName', ' ', '$lastName'])
})
.end()
复制代码
返回如下:
{ "fullName": "Yuanxin Dong" }
复制代码
dateFromString
dateToString
indexOfBytes
在目标字符串中查找子字符串,并返回第一次出现的 UTF-8
的字节索引(从0开始)。如果不存在子字符串,返回 -1。
API
db.command.aggregate.indexOfBytes([<目标字符串表达式>, <子字符串表达式>, <开始位置表达式>, <结束位置表达式>])
复制代码
下面是 4 种表达式的详细描述:
表达式 | 描述 |
---|---|
目标字符串表达式 | 任何可以被解析为字符串的表达式 |
子字符串表达式 | ~~ 字符串的表达式 |
开始位置表达式 | ~~ 非负整数的表达式 |
结束位置表达式 | ~~ 非负整数的表达式 |
示例
集合 students
的记录如下:
{ "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 }
复制代码
借助 indexOfBytes
查找字符 "a"
在字段 firstName
中的位置:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
aStrIndex: $.indexOfBytes(['$firstName', 'a'])
})
.end()
复制代码
返回的结果:
{ "aStrIndex": 2 }
复制代码
indexOfCP
在目标字符串中查找子字符串,并返回第一次出现的 UTF-8
的 code point
索引(从0开始)。如果不存在子字符串,返回 -1。
API
code point
是“码位”,又名“编码位置”。这里特指 Unicode
包中的码位,范围是从0(16进制)到10FFFF(16进制)。
db.command.aggregate.indexOfCP([<目标字符串表达式>, <子字符串表达式>, <开始位置表达式>, <结束位置表达式>])
复制代码
下面是 4 种表达式的详细描述:
表达式 | 描述 |
---|---|
目标字符串表达式 | 任何可以被解析为字符串的表达式 |
子字符串表达式 | ~~ 字符串的表达式 |
开始位置表达式 | ~~ 非负整数的表达式 |
结束位置表达式 | ~~ 非负整数的表达式 |
示例
集合 students
的记录如下:
{ "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 }
复制代码
借助 indexOfCP
查找字符 "a"
在字段 firstName
中的位置:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
aStrIndex: $.indexOfCP(['$firstName', 'a'])
})
.end()
复制代码
返回的结果:
{ "aStrIndex": 2 }
复制代码
split
按照分隔符分隔数组,并且删除分隔符,返回子字符串组成的数组。如果字符串无法找到分隔符进行分隔,返回原字符串作为数组的唯一元素。
API
db.command.aggregate.split([<字符串表达式>, <分隔符表达式>])
复制代码
字符串表达式和分隔符表达式可以是任意形式的表达式,只要它可以被解析为字符串即可。
示例
集合 students
的记录:
{ "birthday": "1999/12/12" }
复制代码
通过 split
将每条记录中的 birthday
字段对应值分隔成数组,每个数组分别由代表年、月、日的3个元素组成:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
birthday: $.split(['$birthday', '/'])
})
.end()
复制代码
返回的结果:
{ "birthday": [ "1999", "12", "12" ] }
复制代码
strLenCP
计算并返回指定字符串的UTF-8 code points 数量。
API
db.command.aggregate.strLenCP(<表达式>)
复制代码
只要表达式可以被解析成字符串,那么它就是有效表达式。
示例
集合 students
的记录如下:
{ "name": "dongyuanxin", "nickname": "心谭" }
复制代码
借助 strLenCP
计算 name
字段和 nickname
字段对应值的UTF-8 code points的数量:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
nameLength: $.strLenCP('$name'),
nicknameLength: $.strLenCP('$nickname')
})
.end()
复制代码
结果:
{ "nameLength": 11, "nicknameLength": 2 }
复制代码
substr
返回字符串从指定位置开始的指定长度的子字符串。它是 db.command.aggregate.substrBytes
的别名,更推荐使用后者。
API
db.command.aggregate.substr([<表达式1>, <表达式2>, <表达式3>])
复制代码
表达式1
是任何可以解析为字符串的有效表达式,表达式2
和 表达式3
是任何可以解析为数字的有效表达式。
如果 表达式2
是负数,返回的结果为 ""
。
如果 表达式3
是负数,返回的结果为从 表达式2
指定的开始位置以及之后其余部分的子字符串。
示例
集合 students
的记录:
{ "birthday": "1999/12/12", "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 }
复制代码
借助 substr
可以提取 birthday
中的年、月、日信息,代码:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
year: $.substr(['$birthday', 0, 4]),
month: $.substr(['$birthday', 5, 2]),
day: $.substr(['$birthday', 8, -1])
})
.end()
复制代码
结果:
{ "day": "12", "month": "12", "year": "1999" }
复制代码
substrBytes
返回字符串从指定位置开始的指定长度的子字符串。子字符串是由字符串中指定的 UTF-8
字节索引的字符开始,长度为指定的字节数。
API
db.command.aggregate.substrBytes([<表达式1>, <表达式2>, <表达式3>])
复制代码
表达式1
是任何可以解析为字符串的有效表达式,表达式2
和 表达式3
是任何可以解析为数字的有效表达式。
如果 表达式2
是负数,返回的结果为 ""
。
如果 表达式3
是负数,返回的结果为从 表达式2
指定的开始位置以及之后其余部分的子字符串。
示例
集合 students
的记录:
{ "birthday": "1999/12/12", "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 }
复制代码
借助 substrBytes
可以提取 birthday
中的年、月、日:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
year: $.substrBytes(['$birthday', 0, 4]),
month: $.substrBytes(['$birthday', 5, 2]),
day: $.substrBytes(['$birthday', 8, -1])
})
.end()
复制代码
结果:
{ "day": "12", "month": "12", "year": "1999" }
复制代码
substrCP
返回字符串从指定位置开始的指定长度的子字符串。子字符串是由字符串中指定的 UTF-8
字节索引的字符开始,长度为指定的字节数。
API
db.command.aggregate.substrCP([<表达式1>, <表达式2>, <表达式3>])
复制代码
表达式1
是任何可以解析为字符串的有效表达式,表达式2
和 表达式3
是任何可以解析为数字的有效表达式。
如果 表达式2
是负数,返回的结果为 ""
。
如果 表达式3
是负数,返回的结果为从 表达式2
指定的开始位置以及之后其余部分的子字符串。
示例
集合 students
的记录如下:
{ "nickname": "心谭" }
复制代码
借助 substrCP
可以提取 nickname
字段值的第一个字:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
firstCh: $.substrCP(['$nickname', 0, 1])
})
.end()
复制代码
结果:
{ "firstCh": "心" }
复制代码
toLower
将字符串转化为小写并返回。
API
db.command.aggregate.toLower(表达式)
复制代码
只要表达式可以被解析成字符串,那么它就是有效表达式。例如:$ + 指定字段
。
示例
集合 students
的记录如下:
{ "firstName": "Yuanxin"}
复制代码
借助 toLower
将 firstName
的字段值转化为小写:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
result: $.toLower('$firstName'),
})
.end()
复制代码
结果:
{ "result": "yuanxin" }
复制代码
toUpper
将字符串转化为大写并返回。
API
db.command.aggregate.toUpper(表达式)
复制代码
只要表达式可以被解析成字符串,那么它就是有效表达式。例如:$ + 指定字段
。
示例
集合 students
的记录如下:
{ "firstName": "Yuanxin", "lastName": "Dong"}
复制代码
借助 toUpper
将 lastName
的字段值转化为大写:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.project({
_id: 0,
result: $.toUpper('$lastName'),
})
.end()
复制代码
结果:
{ "result": "DONG" }
复制代码
累计器操作符
addToSet
向数组中添加值,如果数组中已存在该值,不执行任何操作。它只能在 group stage
中使用。
API
db.command.aggregate.addToSet(<表达式>)
复制代码
表达式是形如 $ + 指定字段
的字符串。如果指定字段的值是数组,那么整个数组会被当作一个元素。
示例
集合 passages
的记录如下:
{ "category": "web", "tags": [ "JavaScript", "CSS" ], "title": "title1" }
{ "category": "System", "tags": [ "C++", "C" ], "title": "title2" }
复制代码
非数组字段
每条记录的 category
对应值的类型是非数组,利用 addToSet
统计所有分类:
const $ = db.command.aggregate
db
.collection('passages')
.aggregate()
.group({
_id: null,
categories: $.addToSet('$category')
})
.end()
复制代码
结果:
{ "_id": null, "categories": [ "System", "web" ] }
复制代码
数组字段
每条记录的 tags
对应值的类型是数组,数组不会被自动展开:
const $ = db.command.aggregate
db
.collection('passages')
.aggregate()
.group({
_id: null,
tagsList: $.addToSet('$tags')
})
.end()
复制代码
结果:
{ "_id": null, "tagsList": [ [ "C++", "C" ], [ "JavaScript", "CSS" ] ] }
复制代码
avg
返回一组集合中,指定字段对应数据的平均值。
API
db.command.aggregate.avg(<number>)
复制代码
avg
传入的值除了数字常量外,也可以是任何最终解析成一个数字的表达式。它会忽略非数字值。
示例
集合 students
的记录如下:
{ "group": "b", "name": "stu3", "score": 80 }
{ "group": "b", "name": "stu4", "score": 100 }
复制代码
借助 avg
可以计算所有记录 score
的平均值:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.group({
_id: null,
average: $.avg('$score')
})
.end()
复制代码
结果:
{ "_id": null, "average": 90 }
复制代码
first
返回指定字段在一组集合的第一条记录对应的值。仅当这组集合是按照某种定义排序( sort
)后,此操作才有意义。
API
db.command.aggregate.first(<表达式>)
复制代码
表达式是形如 $ + 指定字段
的字符串。
first
只能在 group
阶段被使用,并且需要配合 sort
才有意义。
示例
集合 students
的记录如下:
{ "group": "b", "name": "stu3", "score": 80 }
{ "group": "b", "name": "stu4", "score": 100 }
复制代码
如果需要得到所有记录中 score
的最小值,可以先将所有记录按照 score
排序,然后取出第一条记录的 first
。
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.sort({
score: 1
})
.group({
_id: null,
min: $.first('$score')
})
.end()
复制代码
结果:
{ "_id": null, "min": 80 }
复制代码
last
返回指定字段在一组集合的最后一条记录对应的值。仅当这组集合是按照某种定义排序( sort
)后,此操作才有意义。
API
db.command.aggregate.last(<表达式>)
复制代码
表达式是形如 $ + 指定字段
的字符串。
last
只能在 group
阶段被使用,并且需要配合 sort
才有意义。
示例
集合 students
的记录如下:
{ "group": "a", "name": "stu2", "score": 96 }
{ "group": "b", "name": "stu4", "score": 100 }
复制代码
如果需要得到所有记录中 score
的最大值,可以先将所有记录按照 score
排序,然后取出最后一条记录的 last
。
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.sort({
score: 1
})
.group({
_id: null,
max: $.last('$score')
})
.end()
复制代码
结果:
{ "_id": null, "max": 100 }
复制代码
max
返回一组数值的最大值。
API
db.command.aggregate.max(<表达式>)
复制代码
表达式是形如 $ + 指定字段
的字符串。
示例
集合 students
的记录如下:
{ "group": "a", "name": "stu2", "score": 96 }
{ "group": "b", "name": "stu4", "score": 100 }
复制代码
借助 max
可以统计不同组( group
)中成绩的最高值,代码:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.group({
_id: '$group',
maxScore: $.max('$score')
})
.end()
复制代码
结果:
{ "_id": "b", "maxScore": 100 }
{ "_id": "a", "maxScore": 96 }
复制代码
mergeObjects
min
返回一组数值的最小值。
API
db.command.aggregate.min(<表达式>)
复制代码
表达式是形如 $ + 指定字段
的字符串。
示例
集合 students
的记录如下:
{ "group": "a", "name": "stu1", "score": 84 }
{ "group": "a", "name": "stu2", "score": 96 }
{ "group": "b", "name": "stu3", "score": 80 }
{ "group": "b", "name": "stu4", "score": 100 }
复制代码
借助 min
可以统计不同组( group
)中成绩的最低值,代码:
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.group({
_id: '$group',
minScore: $.min('$score')
})
.end()
复制代码
结果:
{ "_id": "b", "minScore": 80 }
{ "_id": "a", "minScore": 84 }
复制代码
push
在 group
阶段,返回一组中表达式指定列与对应的值,一起组成的数组。
API
db.command.aggregate.push({
<字段名1>: <指定字段1>,
<字段名2>: <指定字段2>,
...
})
复制代码
示例
集合 students
的记录如下:
{ "group": "a", "name": "stu1", "score": 84 }
{ "group": "a", "name": "stu2", "score": 96 }
{ "group": "b", "name": "stu3", "score": 80 }
{ "group": "b", "name": "stu4", "score": 100 }
复制代码
借助 push
操作,对不同分组( group
)的所有记录,聚合所有数据并且将其放入一个新的字段中,进一步结构化和语义化数据。
const $ = db.command.aggregate
db
.collection('students')
.aggregate()
.group({
_id: '$group',
students: $.push({
name: '$name',
score: '$score'
})
})
.end()
复制代码
结果:
{ "_id": "b", "students": [{ "name": "stu3", "score": 80 }, { "name": "stu4", "score": 100 }] }
{ "_id": "a", "students": [{ "name": "stu1", "score": 84 }, { "name": "stu2", "score": 96 }] }
复制代码
stdDevPop
返回一组字段对应值的标准差。
API
db.command.aggregate.stdDevPop(<表达式>)
复制代码
表达式传入的是指定字段,指定字段对应的值的数据类型必须是 number
,否则结果会返回 null
。
示例
集合 students
的记录如下:a
组同学的成绩分别是84和96,b
组同学的成绩分别是80和100。
{ "group":"a", "score":84 }
{ "group":"a", "score":96 }
{ "group":"b", "score":80 }
{ "group":"b", "score":100 }
复制代码
可以用 stdDevPop
来分别计算 a
和 b
两组同学成绩的标准差,以此来比较哪一组同学的成绩更稳定。代码:
const $ = db.command.aggregate
db.collection('students').aggregate()
.group({
_id: '$group',
stdDev: $.stdDevPop('$score')
})
.end()
复制代码
结果:
{ "_id": "b", "stdDev": 10 }
{ "_id": "a", "stdDev": 6 }
复制代码
stdDevSamp
计算输入值的样本标准偏差。如果输入值代表数据总体,或者不概括更多的数据,请改用 db.command.aggregate.stdDevPop
。
API
db.command.aggregate.stdDevSamp(<表达式>)
复制代码
表达式传入的是指定字段,stdDevSamp
会自动忽略非数字值。如果指定字段所有的值均是非数字,那么结果返回 null
。
示例
集合 students
的记录:
{ "score": 80 }
{ "score": 100 }
复制代码
可以用 stdDevSamp
来计算成绩的标准样本偏差。代码:
const $ = db.command.aggregate
db.collection('students').aggregate()
.group({
_id: null,
ageStdDev: $.stdDevSamp('$score')
})
.end()
复制代码
结果:
{ "_id": null, "ageStdDev": 14.142135623730951 }
复制代码
如果向集合 students
添加一条新记录,它的 score
字段类型是 string
:
{ "score": "aa" }
复制代码
用上面代码计算标准样本偏差时,stdDevSamp
会自动忽略类型不为 number
的记录,返回结果保持不变。
sum
计算并且返回一组字段所有数值的总和。
API
db.command.aggregate.sum(<表达式>)
复制代码
表达式可以传入指定字段,也可以传入指定字段组成的列表。sum
会自动忽略非数字值。如果字段下的所有值均是非数字,那么结果返回 0。若传入数字常量,则当做所有记录该字段的值都给给定常量,在聚合时相加,最终值为输入记录数乘以常量。
示例
代表商品的集合 goods
的记录如下:price
:商品销售额,cost
:商品成本
{ "cost": -10, "price": 100 }
{ "cost": -15, "price": 1 }
{ "cost": -10, "price": 10 }
复制代码
单独字段
借助 sum
可以计算所有商品的销售总和,代码:
const $ = db.command.aggregate
db
.collection('goods')
.aggregate()
.group({
_id: null,
totalPrice: $.sum('$price')
})
.end()
复制代码
结果
{ "_id": null, "totalPrice": 111 }
复制代码
字段列表
如果需要计算所有商品的利润总额,那么需要将每条的 cost
和 price
相加得到此记录对应商品利润。再计算利润总额。
借助 sum
,代码:
const $ = db.command.aggregate
db
.collection('goods')
.aggregate()
.group({
_id: null,
totalProfit: $.sum(
$.sum(['$price', '$cost'])
)
})
.end()
复制代码
结果:
{ "_id": null, "totalProfit": 76 }
复制代码