node.js - 如何使用 Mongoose 获得嵌套文档的计数字段
问题描述
我有一个带有 Mongoose 的 NodeJS API,我很难计算嵌套在一个文档中的文档。我有一个名为 Profile 的模式,并且嵌套了我体验过的记录数组。我的目标是以输出为例:
{
"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);
}
});
推荐阅读
- javascript - 木偶师在输入字段中写入
- c# - 如何为 Linux 编译和运行 .NET Core Services?
- sql - 在 SQL 中将一行拆分为两部分的问题
- python - 尝试一次通过搜索发送一个列表项
- python - 如何识别单个列中的不同数据类型?
- html - 将选择元素的选项值作为记录的 id (HTML) 是一种好习惯吗?
- javascript - 如何使用 React Native Navigation (v5) 向父页面发送数据?
- git - Git过滤选项卡到空间转换但不显示文件已修改
- python - python中的git命令,无法识别有效的git
- excel - 识别列中前一个单元格值仅在可见范围内不同的行号