对于更新,我使用下面的有效代码:
router.put('/:id', async (req, res) => {
const { error } = validateProduct(req.body);
if (error) return res.status(400).send(error.details[0].message);
const product = await Product.findByIdAndUpdate(req.params.id,
{
name: req.body.name,
description: req.body.description,
category: req.body.category,
tags: req.body.tags,
withdrawn: req.body.withdrawn,
extraData: {
brand: req.body.extraData.brand,
quantity: req.body.extraData.quantity,
type: req.body.extraData.type
}
},
{new: true}
);
if (!product) return res.status(404).send('The product with the given ID was not found.');
res.send(product);
});
我想要做的是创建一个Patch操作,该操作仅更新某些字段,而不是上面更新中的所有字段。这些字段不是标准字段,但它们是更新操作的上述字段之一。
答案 0 :(得分:2)
您可以尝试使用此代码段(尽管未在本地进行测试)。这个想法是只更新req.body中提到的Product中的那些字段。请确保您的验证程序是安全的,否则最终可能会注入nosql。
router.put('/:id', async (req, res) => {
const { error } = validateProduct(req.body);
if (error) return res.status(400).send(error.details[0].message);
const product = await Product.findById(req.params.id).exec();
if (!product) return res.status(404).send('The product with the given ID was not found.');
let query = {$set: {}};
for (let key in req.body) {
if (product[key] && product[key] !== req.body[key]) // if the field we have in req.body exists, we're gonna update it
query.$set[key] = req.body[key];
const updatedProduct = await Product.updateOne({_id: req.params.id}, query}).exec();
res.send(product);
});
另外,我敢肯定,您可以在一行中使用lodash,因为我在其中使用了for-in循环;)
这种方法的缺点是它需要2个查询到mongo,因为您需要一个真实的文档来比较它。同样,更新操作不会触发模型的后保存挂钩。如果需要它们-您应该首先找到findById(),更新必要的字段,然后在找到的文档上点击.save()。 希望对您有帮助
答案 1 :(得分:0)
You could do this as well:
// define your middlewares here
// validateObjectId.js
const mongoose = require('mongoose');
module.exports = function (req, res, next) {
if (!mongoose.Types.ObjectId.isValid(req.params.id))
return res.status(404).send("Invalid ID.");
next();
}
// 404.js
module.exports = function (str, id) {
if (!str || !id) throw new Error('the string name and id must be defined');
return `The ${str} with the given ID (${id}) was not found`;
}
// import your middlewares into your product route
const validateObjectId = require('../middleware/validateObjectId'); // respect your middleware path
const fourOfour = require('../middleware/404'); // respect your middleware path
router.put('/:id', validateObjectId, async (req, res) => {
const { error } = validateProduct(req.body);
const { name, description, category, tags, withdrawn, extraData, } = req.body
if (error) return res.status(400).send(error.details[0].message);
let product = await Product.findById(req.params.id).exec();
if (!product) return res.status(404).send(fourOfour("Product", req.params.id));
product = await Product.findByIdAndUpdate(req.params.id, {
name: name || product.name,
description: description || product.description,
category: category || product.category,
withdrawn: withdrawn || product.withdrawn,
extraData: extraData || product.extraData
}, { new: true });
product = await product.save();
if (!product) return res.status(404).send(fourOfour("Product", req.params.id));
res.send(product);
});