示例1
async list() {
const $ = db.command.aggregate
let res = await db.collection("dcloud-inc").aggregate()
.group({
// 按照 date 字段进行分组
_id: "$date",
// 对 inctype=0 的数据中的 money 进行求和计算,并将所求之和作为 normoney 输出
normoney: {
$sum: {
$cond: {
if: { $eq: ["$inctype", 0] },
then: "$money",
else: 0
}
}
},
// 对 inctype=1 的数据中的 money 进行求和计算,并将所求之和作为 extmoney 输出
extmoney: {
$sum: {
$cond: {
if: { $eq: ["$inctype", 1] },
then: "$money",
else: 0
}
}
},
/*
* 对同一 date 下的所有 mark 合并处理;
* 处理方式:
* 对每条数据的 mark 做非空判断,不为空就将此条 mark+分号,加入到 allmark
* 为空就将空字符串加入到 allmark
*
* 注意:
* 这时输出的 allmark 是一个数组,
* 对非空 mark 拼接分号是为了下一步处理成字符串做准备
*/
allmark: {
$addToSet: {
$cond: {
if: { $ne: ["$mark", ""] },
then: { $concat: ["$mark", ";"] },
else: ""
}
}
}
})
.addFields({
/*
* allmark 字段可能是一个包含多个字符串的数组。
* $reduce 是一个聚合操作符,它会遍历数组中的每个元素并根据定义的逻辑来处理这些元素。
* 在这里,input: "$allmark" 指定了要处理的数组,即 allmark 字段中的值。
* initialValue: "" 表示初始值为空字符串,它是 $reduce 操作的初始累加器的值。
* in: { $concat: ["$$value", "$$this"] } 定义了在每次迭代中如何处理元素。
* $$value 表示当前的累加器值;
* $$this 表示当前处理的元素.在这里,每次迭代都将当前元素连接到累加器值后面。
*/
allmark: {
$reduce: {
input: "$allmark",
initialValue: "",
in: { $concat: ["$$value", "$$this"] }
}
}
})
/*
* 在当前集合和 'dcloud-works' 集合之间建立一个关联,
* 根据当前集合中的 _id 字段与 'dcloud-works' 集合中的 date 字段进行匹配,
* 并将匹配的结果作为一个数组存储在名为 'works' 的新字段中.
*
* 注意:
* 这时输出的 works 是一个数组.
*/
.lookup({
from: 'dcloud-works',
// 当前集合的字段
localField: '_id',
// 关联表中的字段
foreignField: 'date',
// 关联结果存储在 works 中输出
as: 'works',
})
.addFields({
/**
* 这段代码的作用是将字段 works 处理为一个对象。
* 如果 works 是一个空数组,则将 works 设置为一个空对象。
* 如果 works 不是一个空数组,则将 works 数组中的第一个元素输出
*/
works: {
$cond: {
if: {
// 判断数组的长度是否为0
$eq: [ {$size: "$works"}, 0]
},
then: {},
else: { $arrayElemAt: ["$works", 0] }
}
}
})
.sort({
_id: -1
})
.end()
console.log("rk===>[res]", res);
return {
errSubject: '',
errCode: 0,
errMsg: 'ok'
}
}
结果1
{
"affectedDocs": 2,
"data": [
{
"_id": "2024-09",
"normoney": 500000,
"extmoney": 0,
"allmark": "",
"works": {
"_id": "66d812adf2949ce0c74562ab",
"year": "2024",
"date": "2024-09",
"isfull": 1,
"fullday": 30,
"eventhour": 0,
"create_time": 1725436589212,
"update_time": 1725436589212
}
},
{
"_id": "2024-08",
"normoney": 550000,
"extmoney": 120000,
"allmark": "111;",
"works": {
}
}
]
}
示例2
async list() {
const $ = db.command.aggregate
let res = await db.collection("dcloud-inc").aggregate()
.group({
// 同示例1区别
_id: {year:"$year",date:"$date"},
normoney: {
$sum: {
$cond: {
if: { $eq: ["$inctype", 0] },
then: "$money",
else: 0
}
}
},
extmoney: {
$sum: {
$cond: {
if: { $eq: ["$inctype", 1] },
then: "$money",
else: 0
}
}
},
allmark: {
$addToSet: {
$cond: {
if: { $ne: ["$mark", ""] },
then: { $concat: ["$mark", ";"] },
else: ""
}
}
}
})
.addFields({
// 同示例1区别
normoney: { $divide: ["$normoney", 100] },
extmoney: { $divide: ["$extmoney", 100] },
allmark: {
$reduce: {
input: "$allmark",
initialValue: "",
in: { $concat: ["$$value", "$$this"] }
}
}
})
.lookup({
from: 'dcloud-works',
// 同示例1区别
localField: '_id.date',
foreignField: 'date',
as: 'works',
})
.addFields({
works: {
$cond: {
if: { $eq:[ {$size: "$works"}, 0] },
then: {},
else: { $arrayElemAt: ["$works", 0] }
}
}
})
.sort({
_id: -1
})
// 同示例1区别
.group({
_id:"$_id.year",
normoney: { $sum: "$normoney" },
extmoney: { $sum: "$extmoney" },
data:{$push:"$$ROOT"}
})
// 同示例1区别
.addFields({
total:{ $sum: ["$normoney", "$extmoney"] }
})
.sort({
_id: -1
})
.end()
console.log("rk===>[res]", res);
return {
errSubject: '',
errCode: 0,
errMsg: 'ok',
data:res.data,
}
}
结果2
{
"affectedDocs": 1,
"data": [
{
"_id": "2024",
"normoney": 10500,
"extmoney": 1200,
"data": [
{
"_id": {
"year": "2024",
"date": "2024-09"
},
"normoney": 5000,
"extmoney": 0,
"allmark": "",
"works": {
"_id": "66d812adf2949ce0c74562ab",
"year": "2024",
"date": "2024-09",
"isfull": 1,
"fullday": 30,
"eventhour": 0,
"create_time": 1725436589212,
"update_time": 1725436589212
}
},
{
"_id": {
"year": "2024",
"date": "2024-08"
},
"normoney": 5500,
"extmoney": 1200,
"allmark": "111;",
"works": {
}
}
],
"total": 11700
}
]
}