例如,我的数据库中有一些东西,如客户收集。
{
Max: {
shoping_list: {
food: { Pizza: 2, Ramen: 1, Sushi: 5 }
}
},
John: {
shoping_list: {
food: { Pizza: 2, Ramen: 1, Burger: 1 }
}
}
}
在我的后端,我想要得到食物的总和
const request = await customers.aggregate([
{
$group: {
_id: null,
Pizza: {
$sum: '$shoping_list.food.Pizza',
},
是否有一种方法可以自动更新或获取总和,而无需手动从shopping_list
写入每个食物?
文档的设计可能会导致查询看起来很复杂,但仍然可以实现。
-
$replaceRoot
-用新文档替换输入文档1.1。
$reduce
-迭代数组并将其转换为新的形式(数组)。1.2。
input
-将当前文档$$ROOT
的键值对转换为对象数组,例如:[{ k: "", v: "" }]
1.3。
initialValue
-用空数组初始化值。这将导致数组中的输出。1.4。
in
1.4.1。
的聚合数组结果($concatArrays
-结合1.4.2.$$value
)。1.4.2。使用
$cond
运算符过滤出具有{ k: "_id" }
的文档,并通过$objectToArray
将当前迭代对象的v
shoping_list.food
转换为数组。 -
$unwind
-将foods
数组分解为多个文档。 -
$group
-按foods.k
分组,对foods.v
求和。
db.collection.aggregate([
{
$replaceRoot: {
newRoot: {
foods: {
$reduce: {
input: {
$objectToArray: "$$ROOT"
},
initialValue: [],
in: {
$concatArrays: [
"$$value",
{
$cond: {
if: {
$ne: [
"$$this.k",
"_id"
]
},
then: {
$objectToArray: "$$this.v.shoping_list.food"
},
else: []
}
}
]
}
}
}
}
}
},
{
$unwind: "$foods"
},
{
$group: {
_id: "$foods.k",
sum: {
$sum: "$foods.v"
}
}
}
])
Demo @ Mongo Playground