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

Mongoose Mixed类型数组findOneAndUpdate报错:无法读取cardsArray属性

问题背景

我编写了编辑卡片的控制器,用于更新cardsArray对象的字段。由于每个卡片对象的字段不同,cardsArray采用mongoose.Schema.Types.Mixed类型存储。新增卡片的addCard控制器运行正常,但调用editCard控制器时出现类型错误:

TypeError: Cannot read properties of null (reading 'cardsArray')
相关代码及数据

Schema定义

const userSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true,
    },
    email: {
      type: String,
      required: true,
    },
    password: {
      type: String,
      required: true,
    },

    cardsArray: [{ type: mongoose.Schema.Types.Mixed }],
  }
);

MongoDB存储数据

{
  "_id": {
    "$oid": "63b43ab32fc8d3c100cafecc"
  },
  "name": "usern_name",
  "email": "pr****@gmail.com",
  "password": "$2b$12$3nwifHakrBu94BwLXAC4Nu16Kw0.xyW8vAIPTMSgY7cYttVklDIZq",
  "cardsArray": [
    {
      "title": "some_title",
      "category": "Bank",
      "cardHolder": "some_name",
      "cardNumber": "54545454",
      "expiry": "23/01",
      "cvv": "***",
      "logoIndex": 72,
      "isFavourite": false,
      "_id": {
        "$oid": "63b83cc77288d277ef359533"
      }
    }
  ],
  
  "loginIdsArray": [],
  "docsArray": [],
  "activitiesArray": [],
  "__v": 0
}

Add Card控制器代码

addCard: async (req, res) => {
  console.log(req.body.data, req.body.user_id)
  req.body.data._id = newObjectId;
  try {
    const response = await UserDatabase.findOneAndUpdate(
      { _id: req.body.user_id },
      {
        $push: {
          cardsArray: { $each: [req.body.data] },
        },
      },
      { returnOriginal: false }
    );
    res.status(200).send(response);
  } catch (error) {
    console.log(error)
    res.status(404).json({ message: error.message });
  }
},

Edit Card控制器代码

editCard: async (req, res) => {
  const id = req.params.id;

  const { category, title, cardHolder, cardNumber, expiry, cvv, logoIndex, isFavourite } = req.body;
  console.log(req.params.id)

  try {
    const response = await UserDatabase.findOneAndUpdate(
      { _id: "63b43ab32fc8d3c100cafecc", 'cardsArray._id': "63b709fc69a1cfa6fccd645c" },
      {
        $set: {
          "cardsArray.$.title": req.body.title,
          "cardsArray.$.category": req.body.category,
          "cardsArray.$.cardHolder": req.body.cardHolder,
          "cardsArray.$.cardNumber": req.body.cardNumber,
          "cardsArray.$.expiry": req.body.expiry,
          "cardsArray.$.cvv": req.body.cvv,
          "cardsArray.$.logoIndex": req.body.logoIndex,
          "cardsArray.$.isFavourite": req.body.isFavourite
        }
      },
    );

    console.log(response)
    res.status(201).json(response.cardsArray);
  } catch (error) {
    console.log(error)
    res.status(404).json({ message: error.message });
  }
}
错误原因分析
  1. 查询条件不匹配:editCard控制器里硬编码的卡片ID63b709fc69a1cfa6fccd645c与MongoDB数据中实际的卡片ID63b83cc77288d277ef359533不一致,导致findOneAndUpdate找不到匹配文档,返回null。
  2. 未指定返回更新后文档:findOneAndUpdate默认返回更新前的文档,即使找到匹配项,未设置{ new: true }也可能出现数据不一致问题。
  3. 无null值判断:直接访问response.cardsArray,当response为null时触发类型错误。
解决方案
  1. 改用动态参数传递ID:从请求中获取用户ID和卡片ID,避免硬编码,比如从req.body.user_id和req.params.id取值。
  2. 设置返回更新后文档:添加{ new: true }选项,与addCard控制器保持一致。
  3. 增加null值判断:访问response属性前先检查是否为null,提前返回错误信息。

修改后的editCard控制器代码:

editCard: async (req, res) => {
  const cardId = req.params.id;
  const userId = req.body.user_id; // 根据实际请求方式调整获取用户ID的位置

  try {
    const response = await UserDatabase.findOneAndUpdate(
      { _id: userId, 'cardsArray._id': cardId },
      {
        $set: {
          "cardsArray.$.title": req.body.title,
          "cardsArray.$.category": req.body.category,
          "cardsArray.$.cardHolder": req.body.cardHolder,
          "cardsArray.$.cardNumber": req.body.cardNumber,
          "cardsArray.$.expiry": req.body.expiry,
          "cardsArray.$.cvv": req.body.cvv,
          "cardsArray.$.logoIndex": req.body.logoIndex,
          "cardsArray.$.isFavourite": req.body.isFavourite
        }
      },
      { new: true } // 返回更新后的文档
    );

    if (!response) {
      return res.status(404).json({ message: "用户或卡片不存在" });
    }

    res.status(200).json(response.cardsArray);
  } catch (error) {
    console.log(error)
    res.status(500).json({ message: error.message });
  }
}

内容的提问来源于stack exchange,提问作者Praveen Lohar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:31:08