NestJS与Mongoose数据更新异常:Session存储错误求助
问题根源与解决方案
核心问题1:Array.push()的返回值误用
你代码中let newSessions = userSessions.push(...)这一步完全错误——push()方法返回的是数组更新后的长度,不是更新后的数组本身。从控制台输出的2就能看出来,这是添加新元素后数组的长度,你把这个数字转成字符串写回数据库,导致sessions字段变成了"2",而非预期的数组JSON。
核心问题2:未处理非法JSON的边界情况
从MongoDB导出的数据可以看到,部分用户的sessions字段是空字符串("")或非数组的字符串(比如"2"),直接调用JSON.parse()会抛出异常,导致代码崩溃。
修正后的代码
let user = await this.usersModel.findOne({ username: data.username, }); // 处理sessions字段的解析,兼容空值、非法JSON的情况 let userSessions; try { // 先判断是否为空字符串,避免JSON.parse("")报错 userSessions = user.sessions ? JSON.parse(user.sessions) : []; } catch (err) { // 解析失败时默认初始化为空数组 userSessions = []; } console.log(userSessions); // 直接向数组添加元素,push是原地修改,不需要接收返回值 userSessions.push({ os: process.platform, sessionID: sessionID, }); console.log({ os: process.platform, sessionID: sessionID, }); console.log(userSessions); // 现在输出的是完整的数组 await this.usersModel.findOneAndUpdate( { _id: user._id, }, { $set: { // 将更新后的数组转成JSON字符串写回 sessions: JSON.stringify(userSessions), }, } );
额外优化建议
MongoDB本身支持直接存储数组类型,不需要序列化JSON字符串存储。建议修改usersModel,将sessions字段的类型定义为数组,省去手动解析和序列化的步骤,代码更简洁且不易出错:
模型定义示例:
const userSchema = new mongoose.Schema({ // ...其他字段 sessions: { type: Array, default: [] // 默认空数组 } });
简化后的业务代码:
let user = await this.usersModel.findOne({ username: data.username, }); user.sessions.push({ os: process.platform, sessionID: sessionID, }); await user.save(); // 也可以用MongoDB的数组操作符直接更新 // await this.usersModel.findOneAndUpdate( // { _id: user._id }, // { $push: { sessions: { os: process.platform, sessionID: sessionID } } } // );
内容的提问来源于stack exchange,提问作者Almaszosz
相关产品推荐
相关产品推荐

