聚合搜索
聚合主要用来处理数据(统计平均值,求和等)并返回计算后的数据结果。
流水线/管道
聚合是一个流水线式的批处理作业,初始文档经过多个阶段的流水线处理后,得到转换后的聚合结果。
假设已有一个集合 books,其中包含以下格式记录:
[
{
"_id": "xxx",
"category": "Novel",
"name": "The Catcher in the Rye",
"onSale": true,
"sales": 80
}
]
聚合示例如下:
// 云函数端示例
const cloudbase = require("@cloudbase/node-sdk")
const app = cloudbase.init()
const db = app.database()
const $ = db.command.aggregate
exports.main = async (event, context) => {
const res = await db.collection('books').aggregate()
.match({
onSale: true // 是否正在出售
})
.group({
// 按 category 字段分组
_id: '$category',
// 让输出的每组记录有一个 avgSales 字段,其值是组内所有记录的 sales 字段的平均值
avgSales: $.avg('$sales')
})
.end()
return {
res
}
}
第一阶段:match 阶段过滤出了集合中的文档数据(onSale:true
表示找出正在出售的书籍)并传给下一个阶段。
第二阶段:group 阶段基于 category
字段进行分组,并统计出每组中所有记录的 sales
字段平均值。
API 及操作符
参考 Node.js SDK API 文档,一览所有的聚合阶段 API 及 操作符。
优化执行
利用索引
match 和 sort 如果是在流水线的开头的话是可以利用索引的。geoNear 也可以利用地理位置索引,但要注意的是,geoNear 必须是流水线的第一个阶段。
尽早缩小数据集
在不需要集合的全集情况下,应该尽早的通过 match、limit 和 skip 缩小要处理的记录数量。
注意事项
除了 match 阶段,在各个聚合阶段中传入的对象中,可使用的操作符都是聚合操作符,需要特别注意的是,match 进行的是查询匹配,因此语法同普通查询 where 的语法,用的是普通查询操作符。
FAQ
Sort exceeded memory limit of 104857600 bytes
{"Error":{"Code":"FailedOperation","Message":"(Location16820) Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in."},"RequestId":"1728459320973_0.7685102267589137_33591173-19270342dd4_15"}
mongo sort 排序内存溢出问题。
解决方案
- 合理使用project,使用更小的数据集进行排序。
- 合理使用sort,减少排序字段的数量。
- 合理使用match, 尽量在match后,或者最后进行sort。
- 合理使用索引,使用索引进行排序(如果可能的话)。