MongoDB数组无法追加文件,上传文件覆盖原有数据求助
问题根源分析
documents.push报错:你在上传后将documents.push(file)的返回值(数组新长度,数字类型)存入了数据库,导致后续查询时documents变为数字,自然无法调用push方法。- 文件被覆盖:错误地将数组长度存入数据库而非文件数组;同时
req.files是数组,直接push会把整个数组作为单个元素添加,后续错误操作又覆盖了原有数据。 push返回数字:这是JS数组push方法的正常行为——返回数组的新长度,而非修改后的数组本身。
修复方案
1. 推荐:用MongoDB原生数组更新操作(安全高效)
直接通过MongoDB的$push+$each操作符批量添加文件,无需在代码中手动操作数组,避免并发更新问题:
exports.uploadDocuments = async (id, files) => { let document = await User.findByIdAndUpdate( { _id: id }, { $push: { documents: { $each: files } }, // 将req.files的每个元素追加到documents数组 registration_process_value: 99 }, { new: true } ); return document; };
2. 修正控制器代码
无需传入原documents数组,直接传递req.files即可:
exports.updateDocuments = catchAsync(async (req, res) => { try { const check_user = await userService.getUser(req.data.id); if (!check_user) return res.status(404).json({ message: "用户不存在" }); if (check_user.registration_process_value >= 4) { const uploadDocument = await userService.uploadDocuments( check_user.id, req.files ); return res.status(200).json({ data: uploadDocument }); } return res.status(403).json({ message: "注册流程未达到要求步骤" }); } catch (error) { return res.status(400).json({ message: error.message || error }); } });
3. 可选:手动处理数组(不推荐)
如果坚持在代码中操作数组,需注意转换为原生JS数组并合并元素:
exports.uploadDocuments = async (id, documents, files) => { // 将Mongoose数组转为原生JS数组,避免类型问题 const updatedDocuments = [...documents, ...files]; let document = await User.findByIdAndUpdate( { _id: id }, { $set: { documents: updatedDocuments, registration_process_value: 99 }, }, { new: true } ); return document; };
关键注意事项
req.files是数组:因为使用multer.array("documents"),上传的多个文件会被包装为数组,需展开合并到原数组,而非作为单个元素添加。- 不要用
push返回值:JS数组push返回的是新长度,不是修改后的数组,不能直接赋值给存入数据库的变量。 - 优先用MongoDB操作符:
$push+$each是原子操作,能避免并发场景下的数据丢失,比代码层面操作数组更可靠。
内容的提问来源于stack exchange,提问作者John Oliver
相关产品推荐
相关产品推荐

