Node.js+MongoDB:如何仅存储帖子提及的用户名而非完整用户数据
解决MongoDB Post集合Mentions仅存储提及用户名的问题
问题现状
当前Post集合的mentions字段会存储完整的用户文档(包含密码、token等敏感信息),甚至在未提及用户时会存入数据库所有用户数据,示例如下:
{ "userId": "62db90256a7a0d1b38ee15b5", "media": ["nothing"], "mentions": [ { "_id": "62db797c0d2bdc605e6d1810", "Name": "Mitul Kheni", "email": "test@gmail.com", "User_name": "Mitul_kheni", "phoneNumber": "1234567890", "password": "$2a$08$pb6Nu8MlIX7.L0S8vBP6NOFxjc9rZCXOUFA9.IsMBwkENmap946yO", // 其他敏感字段省略 } ] }
错误原因
- 参数接收错误:当前代码试图通过
req.body.User_Name获取提及用户,但这不是正确的参数(前端应传递被提及的用户名列表); - 查询逻辑错误:
User.find({User_Name: req.body.User_Name})如果req.body.User_Name为空或未传,会匹配所有用户,返回完整用户文档; - Schema定义模糊:
mentions字段仅定义为Array,未限制类型,导致可以存入任意数据。
修改方案
1. 修正Post Schema定义
将mentions明确为字符串数组类型,确保仅能存储用户名:
// Post集合Schema mentions: { type: [String], // 明确为字符串数组 default: [], },
2. 修改创建帖子的业务代码
调整参数接收、查询逻辑,仅提取并存储被提及的用户名:
exports.createPost = async (req, res) => { try { const user = await User.findById(req.user._id); if (!user) return res.status(401).json({ message: "No user found" }); // 解构请求参数,获取提及的用户名列表(前端需传递mentions字段,值为用户名数组) const { media, hashTags, postStatus, mentions: mentionedUserNames = [] } = req.body; let mentionUserNames = []; if (mentionedUserNames.length > 0) { // 查询存在的用户,仅返回User_Name字段 const foundUsers = await User.find( { User_Name: { $in: mentionedUserNames } }, { User_Name: 1, _id: 0 } // 投影只取用户名 ); // 提取用户名数组 mentionUserNames = foundUsers.map(u => u.User_Name); // 可选:检查是否有无效用户名 const invalidNames = mentionedUserNames.filter(name => !mentionUserNames.includes(name)); if (invalidNames.length > 0) { return res.status(404).json({ message: `Invalid user names: ${invalidNames.join(', ')}` }); } } const new_post = new Post({ userId: req.user._id, media, mentions: mentionUserNames, // 仅存入用户名数组 hashTags, postStatus, }); const post = await new_post.save(); return res.status(200).send(post); } catch (error) { return res.status(500).send(error.message); } };
关键修改点说明
- 参数调整:从
req.body.mentions获取前端传递的提及用户名列表,默认空数组; - 精准查询:使用
$in操作符匹配多个用户名,通过投影仅返回User_Name字段,避免获取敏感数据; - 空值处理:当没有提及用户时,直接赋值空数组,不会触发全量用户查询;
- 可选验证:添加无效用户名检查,返回明确错误信息。
效果验证
修改后,Post集合的mentions字段将仅存储被提及的用户名,示例如下:
{ "userId": "62db90256a7a0d1b38ee15b5", "media": ["nothing"], "mentions": ["Mitul_kheni", "another_user"], // 其他字段省略 }
内容的提问来源于stack exchange,提问作者Talc
相关产品推荐
相关产品推荐

