子文档更新时触发中间件的解决方法

Solution to trigger the middleware when updating of a subdocument

我使用这个地址模式,并在多个模式中使用它。 一切正常,只有当我更新地址时

const addressSchema = new mongoose.Schema({
    street: String,
    number: String,
    postcode: String,
    city: String,
    comment: String,
    country: {
        type: 'ObjectId',
        ref: 'Country'
    },
    location: {
        type: pointSchema,
        default: () => ({}),
        index: '2dsphere',
    }
});

addressSchema.pre('save', async function (next) {
    console.log('subdocument address pre.save'); // is triggred
    //create geolocation
});


addressSchema.pre('updateOne', async function (next) {
    console.log('subdocument address pre.updateOne'); // not triggred, no error
    //update geolocation
});

Mongoose 的文档只谈到中间件保存和验证。

https://mongoosejs.com/docs/subdocs.html#what-is-a-subdocument-

但是什么是做我想做的最好的解决方案?


附加信息

const pointSchema = new mongoose.Schema({
    type: {
        type: String,
        enum: ['Point'],
        default: 'Point'
    },
    coordinates: {
        type: [Number],
        default: null,
    }
});
const common = require('./common');
const customerSchema = new Schema({
    //...
   address: {
        type: common.addressSchema,
        default: () => ({}),
    },
})

const providerSchema = new Schema({
    //...
   address: {
        type: common.addressSchema,
        default: () => ({}),
    },
})
    "address": {
        "_id": "6043a5f3a8cad615cd8eab3a",
        "location": {
            "type": "Point",
            "coordinates": [
                48.818511962890625,
                2.31961989402771
            ],
            "_id": "603fed0629390b30d53bed3e"
        },
        "street": "Avenue des Tulipes",
        "postcode": "78500",
        "number": "69",
        "city": "Montrouge",
        "comment": null,
        "country": "5f626eb337fd4d75ab694112"
    },

当我们创建新客户时,addressSchema 的中间件 'save' 没有问题,但是当我们更新客户时,所有数据都会正确更新,但不会触发 addressSchema 的中间件 'updateOne' .

我不确定是否有任何直接的方法可以做到这一点,但您可以为所有父模式 customerSchemaproviderSchema 创建预中间件并放置地址更新与否等条件,

  • 如果地址模式在更新中,则创建一个函数来处理对地址模式的操作
function preHookForAddress (_this) {
   // if its "address" object
   if (_this.get('address')) {
        let address = _this.get('address');
        // operation stuff here
        // ..
        // set after update
        _this.set({ address: address });
   }

   // if its "address.location" object
   if (_this.get('address.location')) {
        let address_location = _this.get('address.location');
        // operation stuff here
        // ..
        // set after update
        _this.set({ "address.location": address_location });
   }
}

customerSchema.pre('updateOne', async function (next) {
    await preHookForAddress(this);
    next();
});

providerSchema.pre('updateOne', async function (next) {
    await preHookForAddress(this);
    next();
});