无mongo_id时使用filter删除MongoDB数组元素返回500错误如何解决?
问题原因与解决方案
核心错误点
- 代码中的
articleAllComment是从查询结果中取出的普通JavaScript数组,本身没有MongoDB的save()方法,调用await articleAllComment.save()直接抛出未定义方法异常,这是返回500的根本原因。 - 额外问题:查询参数
q传入的是字符串类型,直接作为数组索引使用可能出现类型匹配问题,需要先转为数字,同时要增加索引合法校验避免数组越界。
修复方案
有两种实现方式可选:
方式1:修改后调用集合的update方法更新文档
不需要自己操作数组后保存,直接对articles集合执行更新操作即可,代码修改如下:
app.delete("/api/articles/:name/delete-comment", (req, res) => { const articleName = req.params.name; // 把索引转成数字 const commentIndex = Number(req.query.q); withDB(async(db) => { try{ const articleInfo = await db.collection('articles').findOne({name:articleName}); // 先校验索引合法性 if (isNaN(commentIndex) || commentIndex < 0 || commentIndex >= articleInfo.comments.length) { return res.status(400).send("评论索引不合法"); } // 过滤要删除的评论 const updatedComments = articleInfo.comments.filter((_, idx) => idx !== commentIndex); // 调用集合的updateOne方法更新文档 await db.collection('articles').updateOne( { name: articleName }, { $set: { comments: updatedComments } } ); res.status(200).send(updatedComments); } catch(err) { console.log(err); // 加打印方便排查错误 res.status(500).send("Error occurred") } },res); });
方式2:直接用MongoDB更新操作符删除指定索引元素
不需要先查文档再过滤,直接通过$unset加$pull一步完成删除,性能更高,也不需要评论有独立的mongo_id:
await db.collection('articles').updateOne( { name: articleName }, // 先把对应索引的元素设为null { $unset: { [`comments.${commentIndex}`]: 1 } } ); // 再移除数组里的null值 await db.collection('articles').updateOne( { name: articleName }, { $pull: { comments: null } } );
额外优化建议
你当前的MongoClient.connect配置参数写法有误,两个配置项应该合并到同一个对象里:
const client = await MongoClient.connect( "mongodb://localhost:27017", { useNewUrlParser: true, useUnifiedTopology: true } );
内容的提问来源于stack exchange,提问作者MagnusEffect
相关产品推荐
相关产品推荐

