我正在尝试在mongoDB上进行微不足道的总和,以计算单个客户端的价格数量。
我的收藏集:
{"_id":"5d973c71dd93adfbda4c7272","name":"Faktura2019006","clientId":"5d9c87a6b9676069c8b5e15b","expiration":"2019-10-02T01:11:18.965Z","price":999999,"userId":"123"},
{"_id":"5d9e07e0b9676069c8b5e15d","name":"Faktura2019007","clientId":"5d9c87a6b9676069c8b5e15b","expiration":"2019-10-02T01:11:18.965Z","price":888,"userId":"123"}
我尝试过的事情:
// invoice.model.js
const mongoose = require("mongoose");
const InvoiceSchema = mongoose.Schema({
_id: String,
name: String,
client: String,
userId: String,
expiration: Date,
price: Number
});
module.exports = mongoose.model("Invoice", InvoiceSchema, "invoice");
和
// invoice.controller.js
const Invoice = require("../models/invoice.model.js");
exports.income = (req, res) => {
console.log("Counting Income");
Invoice.aggregate([
{
$match: {
userId: "123"
}
},
{
$group: {
total: { $sum: ["$price"] }
}
}
]);
};
发生了什么事
当我现在打开浏览器并调用上面的代码时,我在终端中获得控制台日志“ Counting Income”,但是在浏览器中它将永远加载并且什么也没有发生。
很可能我只是想念一些愚蠢的小事,但我试图在很长一段时间内都没有发现任何成功,所以欢迎您提出任何建议。
答案 0 :(得分:0)
控制器永不结束的原因是因为您没有结束响应过程(这意味着您需要使用res
对象并将某些内容发送回调用方)。
为了获得合计值,您还需要执行管道(请参阅this example)。
此外,正如某人在评论中指出的那样,您需要在组中添加_id: null
,以指定您不打算按任何特定字段进行分组(请参见second example here)。
最后,在$sum
运算符中,对于您要执行的操作,您只需要删除数组括号,因为您只想对单个字段求和(请参见a few examples down here)。
这是修改后的代码:
// invoice.controller.js
const Invoice = require("../models/invoice.model.js");
exports.income = (req, res) => {
console.log("Counting Income");
Invoice.aggregate([
{
$match: {
userId: "123"
}
},
{
$group: {
_id: null,
total: { $sum: "$price" }
}
}
]).then((response) => {
res.json(response);
});
};
编辑有关何时返回空数组的注释。
如果您想始终返回相同类型的对象,则可以在控制器中进行控制。我不确定在mongo中是否有一种花哨的方法可以使用聚合管道来做到这一点,但这就是我会做的。
Invoice.aggregate([
{
$match: {
userId: "123"
}
},
{
$group: {
_id: null,
total: { $sum: "$price" }
}
},
{
$project: {
_id: 0,
total: "$total"
}
}
]).then((response) => {
if (response.length === 0) {
res.json({ total: 0 });
} else {
// always return the first (and only) value
res.json(response[0]);
}
});
在这里,如果您发现userId
中的123
,那么您将得到以下内容:
{
"total": 1000887
}
但是如果您将userId
更改为例如数据库中不存在的1123
,则结果将是:
{
"total": 0
}
这样,您的客户端始终可以使用相同类型的对象。
此外,我将$project
流水线放在其中的原因是为了抑制_id
字段(请参见here for more info)。