unicloud聚合查询必须用aggregate()且仅云函数支持全量功能;前端直连受限于环境,h5需配置useunicloud、小程序需基础库≥2.27.0,且仅支持部分stage;$lookup联表须用$.in配合$$变量,时间处理需$todate转毫秒时间戳,分组键必须为对象形式。

uniCloud 的聚合查询必须用 aggregate(),不能用 where() 或 get() 替代;前端直连不支持全部聚合阶段,复杂逻辑务必放在云函数里做。
为什么前端调用 aggregate() 报错或返回空
常见现象是控制台报 TypeError: db.collection(...).aggregate is not a function,或者返回 { result: { data: [] } } 但明明有数据。根本原因不是语法错,而是环境限制:
- 前端(H5、小程序)直连数据库时,
aggregate()仅支持部分 stage(如$match、$group、$project),不支持$lookup、$facet、带变量的$expr等高级操作 - H5 端未在
manifest.json中配置"h5": { "useUniCloud": true },导致前端 SDK 根本没加载聚合能力 - 微信小程序基础库版本低于 2.27.0,
aggregate()不可用 - 字段名大小写不一致或用了未建索引的字段(如
text类型字段参与$match)触发静默失败
云函数里写聚合查询的正确姿势
云函数是唯一能稳定使用全量聚合能力的地方,且无需额外引入 SDK。关键点是显式调用 db.command.aggregate,并注意链式顺序:
- 必须以
.aggregate()开头,中间可链式调用.match()、.addFields()、.group()等,结尾必须是.end() - 时间处理要用
$toDate+$month组合,不能直接对毫秒时间戳字段用$month(否则返回null) - 分组键必须用对象形式:
_id: { month: "$month", campus: "$home_campus" },不能写成字符串_id: "$month" - 聚合结果默认不带
_id字段,如果需要保留原始文档 ID,得用$project显式声明
示例(按月份+校区统计订单数):
const db = uniCloud.database()
const $ = db.command.aggregate
exports.main = async (event, context) => {
const res = await db.collection('xqh_order_1v1')
.aggregate()
.addFields({
month: {
$month: {
date: {
$toDate: '$creat_date' // 注意:字段名必须和数据库一致,且 creat_date 是 number 类型时间戳
}
}
}
})
.group({
_id: { campus: '$home_campus', month: '$month' },
count: $.sum(1)
})
.end()
return res
}
$lookup 联表查数组字段时的坑
当要根据一个数组字段(如 device.instruct_list)去关联另一张表(如 x_device_instruct)时,$lookup 的 pipeline 内必须用 $.in 配合 $$ 引用外部变量,不能用普通 JS 数组方法:
- 错误写法:
match({ instruct_id: { $in: '$$instructs' } })——$in是 MongoDB 原生操作符,不支持变量解构 - 正确写法:
match(_.expr($.in(['$instruct_id', '$$instructs'])))——$.in是 uniCloud 封装的聚合函数,$$instructs是let定义的变量名 -
let中绑定的字段名必须和设备表中数组字段名完全一致(如instruct_list),否则$$xxx取不到值 - 联表后结果存入
as字段(如as: 'instructs'),前端需按数组结构取值,不能直接当对象用
聚合结果字段缺失或类型异常怎么排查
最常被忽略的是时间字段处理和字段名映射。比如 $toDate 输入非数字类型会返回 null,后续 $month 就失效;又比如 addFields 新增字段名含空格或特殊字符,前端 JSON 解析时报错但不提示来源。
- 先在云函数里
console.log(JSON.stringify(res.result.data))看原始输出,确认字段是否存在、是否为null - 检查数据库中源字段类型:时间戳必须是
number(毫秒),不能是string或Date对象(后者序列化后变null) - 聚合中所有引用字段(如
$creat_date)必须加$前缀,漏写就变成字面量字符串 - 前端接收时别直接解构
res.result.data[0].count,先判空,因为聚合可能返回空数组











