这是Issue https://github.com/Automattic/mongoose/issues/6224的副本 .
我将一个名为FileSpace的嵌入式对象创建为一个名为Space的对象数组 . 删除FileSpace时,永远不会调用预删除中间件(但会调用预验证中间件)
这是一个repro代码:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.set('debug', true);
/**
* A file
*/
var FileSpaceSchema = new Schema({
fileKey: {
type: String,
required: true
}
});
// Normally called
FileSpaceSchema.pre('validate', function (next) {
console.log('Calling FileSpace.pre.validate me="%s"', this.fileKey);
next();
});
// Never called !
FileSpaceSchema.pre('remove', function(next) {
console.log(' !!! Calling FileSpace.pre.remove fileKey="%s"', this.fileKey);
next();
});
let FileSpace = mongoose.model('FileSpace', FileSpaceSchema);
/**
* A space containing an array of files
*/
var SpaceDocSchema = new Schema({
label: {
type: 'string',
required: true
},
files: [FileSpaceSchema]
});
SpaceDocSchema.pre('validate', function (next) {
console.log('Calling SpaceDocSchema.preValidate hook spaceDoc is "%s"', this.label);
next();
});
SpaceDocSchema.pre('remove', function (next) {
console.log('Calling Space.post.remove spaceDoc is "%s"', this.label);
next();
});
let SpaceDoc = mongoose.model('SpaceDoc', SpaceDocSchema);
console.log('--> Starting');
console.log('--> Creating a space');
let space = new SpaceDoc({
label: 'The SpaceDoc'
}),
removedFile;
// connect to mongo
mongoose.connect('mongodb://mongodbsrv/clouderialTestDB?w=1&j=true');
mongoose.connection.on('open', () => {
console.log('Connection to MongoDB is effective');
space.save()
.then((s) => {
space = s;
console.log('Created space is "%s"', s.label);
console.log('--> Creating a FileSpace');
return new FileSpace({fileKey : 'fileSpace', spaceLabel:'The space label'}).save();
})
.then((fs) => {
console.log('Created FileSpace is "%s"', fs.fileKey);
console.log('--> Add fileSpace into SpaceDoc.files');
space.files.push(fs);
space.markModified('files');
return space.save();
})
.then((s) => {
space = s;
console.log('Updated space is "%s", nbFiles="%d"', space.label, space.files.length);
console.log('--> Remove fileSpace from space');
removedFile = space.files[0];
space.files.splice(0, 1);
// space.files = [];
space.markModified('files');
console.log('--> Update space without file');
return space.save();
})
.then((s) => {
space = s;
console.log('Updated space is "%s", nbFiles="%d"', space.label, space.files.length);
console.log('--> Remove fileSpace');
return removedFile.remove();
})
.then(() => {
console.log('--> Should see the call to pre.remove of FileSpace');
console.log('--> Remove space');
return space.remove();
})
.catch(console.error);
});
setTimeout(() => {
console.log('--> Close MongoDB connection');
mongoose.connection.close();
}, 3000);
输出如下:
$ npm start
> test@0.0.1 start /datas/cld-apps/test
> NODE_PATH=/home/vagrant/cld-apps/node_modules:. TZ=Europe/Paris node test.js
--> Starting
--> Creating a space
Connection to MongoDB is effective
Calling SpaceDocSchema.preValidate hook spaceDoc is "The SpaceDoc"
Mongoose: spacedocs.insert({ label: 'The SpaceDoc', files: [], _id: ObjectId("5aa18e47f13311778fdc3beb"), __v: 0 })
Created space is "The SpaceDoc"
--> Creating a FileSpace
Calling FileSpace.pre.validate me="fileSpace"
Mongoose: filespaces.insert({ fileKey: 'fileSpace', _id: ObjectId("5aa18e47f13311778fdc3bec"), __v: 0 })
Created FileSpace is "fileSpace"
--> Add fileSpace into SpaceDoc.files
Calling SpaceDocSchema.preValidate hook spaceDoc is "The SpaceDoc"
Calling FileSpace.pre.validate me="fileSpace"
Mongoose: spacedocs.update({ _id: ObjectId("5aa18e47f13311778fdc3beb"), __v: 0 }, { '$set': { files: [ { fileKey: 'fileSpace', _id: ObjectId("5aa18e47f13311778fdc3bec"), __v: 0 } ] }, '$inc': { __v: 1 } })
Updated space is "The SpaceDoc", nbFiles="1"
--> Remove fileSpace from space
--> Update space without file
Calling SpaceDocSchema.preValidate hook spaceDoc is "The SpaceDoc"
Mongoose: spacedocs.update({ _id: ObjectId("5aa18e47f13311778fdc3beb"), __v: 1 }, { '$set': { files: [] }, '$inc': { __v: 1 } })
Updated space is "The SpaceDoc", nbFiles="0"
--> Remove fileSpace
--> Should see the call to pre.remove of FileSpace
--> Remove space
Calling Space.post.remove spaceDoc is "The SpaceDoc"
Mongoose: spacedocs.remove({ _id: ObjectId("5aa18e47f13311778fdc3beb") }, {})
--> Close MongoDB connection
What is the expected behavior? 我们应该看到日志行:
!!! Calling FileSpace.pre.remove fileKey
Please mention your node.js, mongoose and MongoDB version. 节点9.5.0,Mongoose 5.0.9,MongoDB 3.6.3,Mongo驱动程序:3.0.3
编辑:如果我删除space.files.push(fs)行,正确调用中间件 . 仅当fileSpace放在空间对象的数组中时才会发生pb .