子文档更新时触发中间件的解决方法
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' .
我不确定是否有任何直接的方法可以做到这一点,但您可以为所有父模式 customerSchema
和 providerSchema
创建预中间件并放置地址更新与否等条件,
- 如果地址模式在更新中,则创建一个函数来处理对地址模式的操作
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();
});
我使用这个地址模式,并在多个模式中使用它。 一切正常,只有当我更新地址时
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' .
我不确定是否有任何直接的方法可以做到这一点,但您可以为所有父模式 customerSchema
和 providerSchema
创建预中间件并放置地址更新与否等条件,
- 如果地址模式在更新中,则创建一个函数来处理对地址模式的操作
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();
});