You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 14:10:21