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

MongoDB同一文档同时使用$set与$pull操作失效问题咨询

问题原因分析
  • $pull 语法使用错误:当同时执行三类操作时,待删除的图片参数imagesDelete为数组格式,你原写法{"filename": imagesDelete }要求MongoDB匹配filename字段完全等于整个数组的图片条目,不存在符合条件的数据,会导致删除操作失效。部分MongoDB版本会将这类无效匹配的更新请求判定为非法,连带同批次的$set字段修改也不执行,最终整个更新逻辑异常。
  • Cloudinary 删除未做异步等待:你使用回调方式调用Cloudinary删除接口,代码不会等待删除完成就直接执行后续数据库操作,若删除过程报错,回调内的响应返回逻辑会因为主请求已经响应完成,触发「无法重复设置响应头」的异常,直接导致接口报错。
修复方案

核心修改点

  1. 动态构造更新对象,当存在待删除图片时,使用$in匹配数组内的所有待删除文件名
  2. 将Cloudinary删除操作改为Promise异步等待调用,避免回调导致的时序问题
  3. 统一处理单张/多张删除的逻辑,无需单独判断字符串/数组类型
  4. 新增上传图片判空逻辑,避免无新图片上传时报错

修复后完整代码

exports.editarProductoUser = async (req, res, next) => {
  // 校验参数错误
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  console.log(req.body);
  const { imagesDelete, title, categoria, subCategoria, price, description, contacto } = req.body;

  try {
    // 校验商品是否存在
    const productoTest = await Producto.findById(req.params.id);
    if (!productoTest) {
      console.log("hay un error en edicion");
      return res.status(404).json({ msg: "Producto no encontrado" });
    }

    // 校验操作权限
    if (productoTest.author.toString() !== req.user.id) {
      return res.status(401).json({ msg: "No Autorizado para Editar" });
    }

    // 处理Cloudinary图片删除
    if (imagesDelete !== undefined) {
      const deleteList = Array.isArray(imagesDelete) ? imagesDelete : [imagesDelete];
      for (let filename of deleteList) {
        try {
          await cloudinary.uploader.destroy(filename);
        } catch (err) {
          console.log(err);
          return res.status(400).json({
            ok: false,
            message: "Error deleting file",
            errors: err,
          });
        }
      }
    }

    // 动态构造更新语句
    const updateOps = {
      $set: { title, categoria, subCategoria, price, description, contacto }
    };
    if (imagesDelete !== undefined) {
      const deleteList = Array.isArray(imagesDelete) ? imagesDelete : [imagesDelete];
      updateOps.$pull = {
        images: { filename: { $in: deleteList } }
      };
    }

    // 执行更新操作
    const producto = await Producto.findByIdAndUpdate(
      req.params.id, 
      updateOps,     
      { new: true }
    );

    // 新增上传的图片
    if (req.files?.length) {
      const images = req.files.map((f) => ({
        url: f.path,
        filename: f.filename,
      }));
      producto.images.push(...images);
      await producto.save();
    }

    res.json({ producto });
  } catch (error) {
    console.log(error);
    res.status(500).send("Hubo un Error");
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:15:07