Node.js+MongoDB API:PUT请求返回成功但未更新字段
问题:PUT请求返回成功但MongoDB字段未实际更新
我正在开发一个用于检索和更新MongoDB数据的API,目前GET请求可以正常获取数据,但执行PUT请求时,虽然返回了Field replaced successfully,但通过GET验证发现数据库中的字段并未发生变化。API要求请求携带以下参数:
key:必填的请求授权参数id:指定要检索或更新的字段
数据库结构示例:
{ "userId": { "customs": [ "Sword", "Spear" ], "morphs": [ "Knight", "Jester" ] } }
相关代码如下:
var Express = require("express"); var MongoClient = require("mongodb").MongoClient; var cors = require("cors") const multer = require("multer") var app = Express() app.use(cors()); app.use(Express.json()); var connection_string = "connection-string" var validKey = "60YGrhgU6MEz9E1UZmaMLFlAvKTbYGLGof3PRTmvAmxYWXQeeXIbjPiFhUUVaWqBc" var databaseName = "data" var database; app.listen(5038, () => { MongoClient.connect(connection_string, (error, client) => { database = client.db(databaseName); console.log("Connected to MongoDB") }); }) app.get('/api/lsbg', (request, response) => { const key = request.query.key; const id = request.query.id; if (key !== validKey) { response.status(401).send({ "code": 401, "error": "Invalid key" }) } else { if (!id) { database.collection("giver").find({}).forEach(doc => { response.send(doc) }) } else if (id === 0) { database.collection("giver").find({}).forEach(doc => { response.send(doc) }) } else { database.collection('giver').findOne({}, (error, result) => { if (error) { response.status(404).json({ "code": 500, error: 'Internal server error' }); } else if (result && result.hasOwnProperty(id)) { response.json(result[id]); } else { response.status(404).json({ "code": 404, error: `Could not find data of id ${id}` }); } }); } } }) app.put('/api/lsbg', (req, res) => { const id = req.params.id; const updatedValue = req.body; const updateQuery = { [id]: updatedValue }; database.collection('giver').updateOne( {}, { $set: updateQuery }, (error, result) => { if (error) { res.status(500).json({ error: 'Internal server error' }); } else { res.json({ message: 'Field replaced successfully' }); } } ) });
问题根源分析
id参数获取错误:PUT接口中尝试从req.params.id获取id,但路由/api/lsbg并未定义路径参数(如/api/lsbg/:id),根据需求id是作为查询参数传递的(与GET接口一致),因此实际id值为undefined,导致$set的键无效,没有更新任何字段。- 缺少
key授权验证:PUT接口未校验请求中的key参数,既存在安全隐患,也不符合API参数要求。 - 更新结果未校验:无论
updateOne是否实际修改了文档,都会返回成功提示,无法区分“执行成功但无文档被修改”和“真正更新成功”的情况。
修复后的PUT接口代码
app.put('/api/lsbg', (req, res) => { const key = req.query.key; const id = req.query.id; const updatedValue = req.body; // 验证key合法性 if (key !== validKey) { return res.status(401).send({ "code": 401, "error": "Invalid key" }); } // 验证id是否存在 if (!id) { return res.status(400).json({ "code": 400, error: "id parameter is required" }); } const updateQuery = { [id]: updatedValue }; database.collection('giver').updateOne( {}, // 建议添加明确文档匹配条件(如{ _id: xxx }),避免误修改集合中其他文档 { $set: updateQuery }, (error, result) => { if (error) { return res.status(500).json({ "code": 500, error: 'Internal server error' }); } // 检查是否有文档被实际修改 if (result.modifiedCount === 0) { return res.status(404).json({ "code": 404, error: `Could not find field with id ${id} or no changes made` }); } res.json({ message: 'Field replaced successfully' }); } ) });
额外优化建议
- 修正GET接口中
find({}).forEach(doc => response.send(doc))的问题:response.send只能调用一次,后续调用会报错,建议用toArray()统一返回所有文档:database.collection("giver").find({}).toArray((err, docs) => { if (err) return res.status(500).json({ error: 'Internal server error' }); res.send(docs); }); - 在
updateOne的查询条件中添加明确的文档匹配规则(如根据_id或唯一字段),避免误修改集合中的其他文档。
内容的提问来源于stack exchange,提问作者kesect
相关产品推荐
相关产品推荐

