猫鼬文档更新时如何触发功能
How to trigger a function whenever a mongoose document is updated
我在 mongoose 中有一个用户模型模式,其中包含朋友和群组的列表以及 stats
信息,就像这样...
var user = new Schema({
email: { type: String, required: true, unique: true },
password: { type: String, required: true, select: false },
roles: [{ type: String, required: true }],
friends: [{ type: Schema.Types.ObjectId, ref: 'User' }],
groups: [{ type: Schema.Types.ObjectId, ref: 'Group' }],
stats : {
nbrFriends: { type: Number, required: false },
nbrGroups: { type: Number, required: false }
}
}, {
timestamps: true
});
每当对 friends
或 groups
字段进行更改以包含 friends
或 [=16] 的新数量时,我需要更新用户 stats
=] 等。例如,当对用户调用以下函数时:
var addGroup = function(user, group, cb) {
user.groups.push(group);
User.findOneAndUpdate({ _id: user._id }, { $set: { groups: user.groups }}, { new: true }, function(err, savedResult) {
if(err) {
return cb(err);
}
console.log('updated user: ' + JSON.stringify(savedResult));
return cb(null, savedResult);
});
};
如何确保 stats
自动更新以包含用户拥有的 groups
的新号码?中间件功能似乎是这里最好的方法。我尝试了以下方法,但这似乎从未被调用过...
user.pre('save', function(next) {
var newStats = {
nbrGroups: this.groups.length,
nbrPatients: this.friends.length
};
this.stats = newStats;
this.save(function(err, result) {
if(err) {
console.log('error saving: ' + err);
} else {
console.log('saved');
}
next();
});
});
您需要使用中间件a.k.a。钩子:
Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions.
查看文档:
您应该使用 vanilla JS 进行更新,然后保存更新后的文档以触发预保存挂钩。
如果您有很多键要更新,您可以遍历正文中的键并一个一个地更新。
const user = await User.findById(id);
Object.keys(req.body).forEach(key => {
user[key] = req.body[key];
}
const saved = await user.save();
从version 3.6开始,您可以使用change streams
。
喜欢:
const Users = require('./models/users.js')
var filter = [{
$match: {
$and: [{
$or:[
{ "updateDescription.updatedFields.friends": { $exists: true } },
{ "updateDescription.updatedFields.groups": { $exists: true } },
]
{ operationType: "update" }]
}
}];
var options = { fullDocument: 'updateLookup' };
let userStream = Users.watch(filter,options)
userStream.on('change',next=>{
//Something useful!
})
我在 mongoose 中有一个用户模型模式,其中包含朋友和群组的列表以及 stats
信息,就像这样...
var user = new Schema({
email: { type: String, required: true, unique: true },
password: { type: String, required: true, select: false },
roles: [{ type: String, required: true }],
friends: [{ type: Schema.Types.ObjectId, ref: 'User' }],
groups: [{ type: Schema.Types.ObjectId, ref: 'Group' }],
stats : {
nbrFriends: { type: Number, required: false },
nbrGroups: { type: Number, required: false }
}
}, {
timestamps: true
});
每当对 friends
或 groups
字段进行更改以包含 friends
或 [=16] 的新数量时,我需要更新用户 stats
=] 等。例如,当对用户调用以下函数时:
var addGroup = function(user, group, cb) {
user.groups.push(group);
User.findOneAndUpdate({ _id: user._id }, { $set: { groups: user.groups }}, { new: true }, function(err, savedResult) {
if(err) {
return cb(err);
}
console.log('updated user: ' + JSON.stringify(savedResult));
return cb(null, savedResult);
});
};
如何确保 stats
自动更新以包含用户拥有的 groups
的新号码?中间件功能似乎是这里最好的方法。我尝试了以下方法,但这似乎从未被调用过...
user.pre('save', function(next) {
var newStats = {
nbrGroups: this.groups.length,
nbrPatients: this.friends.length
};
this.stats = newStats;
this.save(function(err, result) {
if(err) {
console.log('error saving: ' + err);
} else {
console.log('saved');
}
next();
});
});
您需要使用中间件a.k.a。钩子:
Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions.
查看文档:
您应该使用 vanilla JS 进行更新,然后保存更新后的文档以触发预保存挂钩。
如果您有很多键要更新,您可以遍历正文中的键并一个一个地更新。
const user = await User.findById(id);
Object.keys(req.body).forEach(key => {
user[key] = req.body[key];
}
const saved = await user.save();
从version 3.6开始,您可以使用change streams
。
喜欢:
const Users = require('./models/users.js')
var filter = [{
$match: {
$and: [{
$or:[
{ "updateDescription.updatedFields.friends": { $exists: true } },
{ "updateDescription.updatedFields.groups": { $exists: true } },
]
{ operationType: "update" }]
}
}];
var options = { fullDocument: 'updateLookup' };
let userStream = Users.watch(filter,options)
userStream.on('change',next=>{
//Something useful!
})