Node.js Mongoose:更新文档并使用中间件

Node.js Mongoose:更新文档并使用中间件,node.js,express,mongoose,Node.js,Express,Mongoose,我有一个例子,我使用mongoose.pre'save'钩子将一些数据反规范化为其他文档。我正在努力寻找一个好的解决方案来更新数据,并在整个数据库中保持非规范化的一致性。如果我想更新一个文档,我考虑三个备选方案: 执行原子更新 我不喜欢这样做的原因是它不会触发我的mongoose中间件,我需要去规范化我的数据 使用.post'update'挂钩 这个方法的问题在于我无法在钩子中分辨哪些字段已经更新,对吗?那么我应该假设所有字段都已更新,并对整个数据库中的数据进行了非规范化处理?看起来很紧张 获取

我有一个例子,我使用mongoose.pre'save'钩子将一些数据反规范化为其他文档。我正在努力寻找一个好的解决方案来更新数据,并在整个数据库中保持非规范化的一致性。如果我想更新一个文档,我考虑三个备选方案:

执行原子更新 我不喜欢这样做的原因是它不会触发我的mongoose中间件,我需要去规范化我的数据

使用.post'update'挂钩 这个方法的问题在于我无法在钩子中分辨哪些字段已经更新,对吗?那么我应该假设所有字段都已更新,并对整个数据库中的数据进行了非规范化处理?看起来很紧张

获取文档,修改它,然后保存它 这似乎很方便,但会造成覆盖数据的风险,即如果文档是在“中间”时刻从其他地方更新的

在models/car.model.js中:

在controllers/car.controller.js中:


任何一种解决方案都可以做到两全其美吗?

第二种是可行的选择,你可以在你的“更新”挂件中使用。另外,执行原子更新(如updateOne)有什么错


另外,很高兴看到您正在使用异步中间件,但仅供参考,您不需要。

谢谢Valeri!我在现在更新的问题中添加了另一个示例。也许我想使用中间件来获取制造商并将其部分数据存储在文档中。这就是我为什么不使用原子更新的原因。但也可能是我想更新任何引用我的汽车文档数据的文档。在您的新示例中,如果制造商发生更改,则从制造商模型中提取数据的方法是正确的。但是,您还需要制造商模型上相应的中间件来更新引用该制造商的任何汽车文档。
const { mongoose } = require('mongoose');
const Schema = mongoose.Schema;

const Manufacturer = require('./manufacturer.model.js');

const CarSchema = new Schema({
    name: String,
    manufacturer: {
        type: {
            _id: Schema.Types.ObjectId,
            name: String,
        },
    },
});

CarSchema.pre('save', async function(next) {
    /*
    if (this.isModified('name')) {
        await Manufacturer.findByIdAndUpdate(this.manufacturer, {
            $set: {
                car-name: this.name,
            },
        });
    }
    */
    if (this.isModified('manufacturer') {
        const manufacturer = await Manufacturer.findOne({
            _id: this.manufacturer._id,
        }, {
            name: 1,
        });
        this.manufacturer.name = manufacturer.name;
    }
});
app.patch('/:id', async function (req, res, next) {
    const car = await Car.findById(req.params.id);
    // Bad solution, helps please
    for (var key in req.body) {
        car[key] = req.body[key];
    }
    await car.save();
    res.sendStatus(200);
});