[英]Mongoose - Count documents for each unique value of a field
[英]How to have a count field of nested documents with Mongoose
我有一个带有 Mongoose 的 NodeJS API,我无法计算嵌套在一个文档中的文档数。 我有一个名为 Profile 的架构,并且嵌套了 I have Experienced 的记录数组。 我的目标是以输出为例:
{
"username": "Jakos",
"total_expereinces" = 2, << I want to add this
"experience": [
{
"image": "",
"_id": "5e26ff6d5be84a3aeeb2f7bc",
"title": "Senior Dev",
"role": "Dev",
"company": "ArosaDev",
"startDate": "2018-12-03T23:00:00.000Z",
"endDate": null,
"description": "",
"area": "",
"createdAt": "2020-01-21T13:41:01.873Z",
"updatedAt": "2020-01-21T13:41:01.873Z"
},
{
"image": "https://via.placeholder.com/150",
"_id": "5e28791604718d7edb521c5b",
"role": "Dev",
"company": "Mammamia",
"startDate": "2019-12-11T23:00:00.000Z",
"endDate": null,
"description": "",
"area": "Copenhagen",
"createdAt": "2020-01-22T16:32:22.848Z",
"updatedAt": "2020-01-22T16:32:22.848Z"
}
]
}
目前我可以在没有计数的情况下获得所有内容,我的方法如下:
experienceRouter.get("/:username", async (req, res) => {
console.log(req.params.username);
try {
const experiences = await Profiles.findOne(
{ username: req.params.username },
{ experience: 1, username: 1, _id: 0 }
).lean();
if (experiences) res.send(experiences);
res.status(404).send({ Message: "Not found any experience" });
} catch (error) {
res.status(500).send(err);
}
});
我看到了一个带有聚合的示例,我试图遵循,但输出与我的要求不同,因为它在输出中显示了整个配置文件。
我尝试使用聚合的方法是:
experienceRouter.get("/:username", async (req, res) => {
console.log(req.params.username);
try {
const numberOfExperiences = await Profiles.aggregate([
{ $match: { username: req.params.username } },
{ $unwind: "$experience" },
{ $project: { count: { $add: 1 } } },
{ $group: { _id: null, number: { $sum: "$count" } } }
]);
const experiences = await Profiles.findOne({
username: req.params.username
});
if (numberOfExperiences) {
if (experiences) res.send({ numberOfExperiences, experiences });
}
} catch (err) {
res.status(500).send(err);
}
});
但是输出并不像我需要的那样好,这就是我所看到的:
{
"numberOfExperiences": [
{
"_id": null,
"number": 4
}
],
"experiences": {
"imageUrl": "https://via.placeholder.com/150",
"_id": "5e26ff6d5be84a3aeeb2f7bb",
"firstname": "Jakub",
"surname": "Lemiszewski",
"email": "jakub@email.com",
"bio": "IT Geek",
"title": "Senior Dev",
"area": "Copenhagen",
"username": "Jakos",
"experience": [
{
"image": "",
"createdAt": "2020-01-21T13:41:01.873Z",
"updatedAt": "2020-01-21T13:41:01.873Z",
"_id": "5e26ff6d5be84a3aeeb2f7bc",
"title": "Senior Dev",
"role": "Dev",
"company": "ArosaDev",
"startDate": "2018-12-03T23:00:00.000Z",
"endDate": null,
"description": "",
"area": ""
},
我需要根据我在项目中的要求在开始时显示输出,并且我遇到了这样做的问题。
您可以使用$size聚合运算符来获取经验计数,并使用$addFields聚合将其添加到结果中。
db.collection.aggregate([
{
$match: {
"username": "Jakos"
}
},
{
$addFields: {
"experiences_count": {
$size: "$experience"
}
}
},
{
$project: {
experiences_count: 1,
username: 1,
experience: 1,
_id: 0
}
}
])
输出:
[
{
"experience": [
{
"_id": "5e26ff6d5be84a3aeeb2f7bc",
"area": "",
"company": "ArosaDev",
"createdAt": "2020-01-21T13:41:01.873Z",
"description": "",
"endDate": null,
"image": "",
"role": "Dev",
"startDate": "2018-12-03T23:00:00.000Z",
"title": "Senior Dev",
"updatedAt": "2020-01-21T13:41:01.873Z"
},
{
"_id": "5e28791604718d7edb521c5b",
"area": "Copenhagen",
"company": "Mammamia",
"createdAt": "2020-01-22T16:32:22.848Z",
"description": "",
"endDate": null,
"image": "https://via.placeholder.com/150",
"role": "Dev",
"startDate": "2019-12-11T23:00:00.000Z",
"updatedAt": "2020-01-22T16:32:22.848Z"
}
],
"experiences_count": 2,
"username": "Jakos"
}
]
示例沙箱
所以你可以像这样重写你的代码:
experienceRouter.get("/:username", async (req, res) => {
console.log(req.params.username);
try {
const profileWithExperiences = await Profiles.aggregate([
{ $match: { username: req.params.username } },
{
$addFields: {
experiences_count: {
$size: "$experience"
}
}
},
{
$project: {
experiences_count: 1,
username: 1,
experience: 1,
_id: 0
}
}
]);
if (profileWithExperiences.length > 0) {
res.send({ profile: profileWithExperiences });
//you can also return like this
//res.send({ profile: profileWithExperiences[0] });
} else {
res.status(400).send("No profile found for username");
}
} catch (err) {
console.log(err);
res.status(500).send(err);
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.