如何在MongoDB中使用findOne查询并排除数组中的嵌套transactions字段
问题原因
你原来的代码有两处核心错误:
- 不能链式调用
findById()和aggregate(),聚合查询需要直接在模型上调用,通过$match阶段筛选指定id的用户 - 你的
$project路径写错了,data下的键是动态的TYPE_1、TYPE_2这类值,你写的data.v.transactions不存在,无法匹配到嵌套的transactions字段
正确实现代码
const mongoose = require('mongoose'); getUserData = async (req, res) => { const { id } = req.params; try { const userData = await UserModel.aggregate([ // 第一步:筛选指定_id的用户 { $match: { _id: mongoose.Types.ObjectId(id) } }, // 第二步:过滤所有嵌套的transactions字段 { $project: { email: 1, createdAt: 1, updatedAt: 1, data: { $arrayToObject: { $map: { input: { $objectToArray: "$data" }, // 将data对象转为[key, value]数组 as: "typeItem", in: { k: "$$typeItem.k", // 保留原类型键名,比如TYPE_1、TYPE_2 v: { $map: { input: "$$typeItem.v", // 遍历每个类型下的数组元素 as: "dataItem", in: { // 保留除了transactions之外的所有字段 type: "$$dataItem.type", profile: "$$dataItem.profile", summary: "$$dataItem.summary" } } } } } } } } } ]); // aggregate返回的是数组,所以要判断长度 if (!userData.length) return res.status(400).json({ success: false, message: `No data found` }); res.status(200).send(userData[0]); } catch (error) { console.error(error); res.status(400).send({ status: false, error }); } }
补充说明
如果你data下的每个元素除了transactions之外还有其他不定字段,不想逐个写保留字段,可以用$unset替换上面的显式指定字段逻辑,把内层$map的in部分换成:
in: { $unset: "$$dataItem.transactions" }
这个写法需要你的MongoDB版本 >= 5.0才支持。
内容的提问来源于stack exchange,提问作者Gaurav
相关产品推荐
相关产品推荐

