updating collection with mongoose after an aggregation
我目前正在一家小型公司工作,担任实习生,并且正在开发类似如下的用户架构:
1 2 3 4 5 6 7 8 9 10 11 12 13 | var UserSchema = new Schema({ name: String, email: { type: String, unique: true }, username: { type: String, unique: true }, hashed_password: String, provider: String, salt: String, |
,由于我正在处理的应用程序发生更改,因此我更新了此架构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | var UserSchema = new Schema({ name: String, email: { type: String, unique: true }, username: { type: String, unique: true }, hashed_password: String, provider: String, salt: String, stats : { bricks: Number,// Number of bricks created by an user layers: Number,// --------- layers ------------------ projects: Number,//-------- projects ---------------- lastogin: Date }, }); |
当然,在线存在该应用程序的旧版本,我需要更新用户集中现有的所有用户。
为此,我需要计算每个用户创建的每个砖块/层/项目。这是砖模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | /************** App fields **************/ // False deletion field field.deleted = function() { return field.bool(); }; // Creation date field.created = function() { return field.date(); }; // Title Field field.title = function() { return field.string(); }; // Desc Field field.desc = function() { return field.string(); }; // Default short Id field field.shortId = function(id) { return { type: ShortId, index: true, len: 7, // Length 7 characters base: 64, // Web-safe base 64 encoded string alphabet:"abcdefghijklmnopkrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", // Use default alphabet for base retries: 4 // Four retries on collision }; }; // The author of the content field.user = function() { return { user: field.ref('User'), } }; field.favorites = function() { return [{ type: Schema.ObjectId, ref: 'User' }]; }; field.contributors = function() { return [{ type: Schema.ObjectId, ref: 'User' }]; }; field.comments = function() { return [{ // user that have written the comment user: field.ref('User'), // comment text it-self comment: field.string() }]; }; |
经过一番研究,我决定使用mongoose(和mongodb)的聚合管道根据用户使用以下查询对砖进行分组:
1 2 3 4 5 6 7 8 9 | db.bricks.aggregate( [ { $group : { _id :"$user", count : { $sum : 1} } ] ) |
以及以下使用猫鼬的方法:
1 2 3 4 5 6 7 8 | var promise =Brick.aggregate() .group({ _id:"$user"}) .exec(function (err, res) { if (err) return handleError(err); else { console.log(res); } }); |
我知道exec()方法会返回一个promise,但我仍在学习如何正确使用它。
之后,我想对所有用户执行更新查询。由于它们没有创建相同数量的积木,因此我无法进行多次更新,因此需要使用如下查询循环遍历结果:
1 | User.update({id : user_id}, {$set : {"stats.bricks" : Brick.find({user : user_id}).count()}}) |
是否可以通过这种方式做到?还是我需要以其他方式重新思考问题?
我尝试了其他方法,并成功获得了想要的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | exports.updatesUsersStats = function (req, res) { User.find().exec(function(err, users) { console.log(users.length); _.each(users, function(currentUser) { console.log("Count bricks user :" +currentUser._id); Brick.find({user : currentUser._id}) .exec(function(err, bricks) { if(err) return handleError(err); console.log("Update user :"+ currentUser._id); User.update({_id : currentUser._id}, {$set : {"stats.bricks" : bricks.length}}) .exec(function(err) { if(err) return handleError(err); }); }); }); res.jsonp({ updateType :"updateUserStats", operations : users.length }); }); }; |
我撇开了考虑所有用户(未创建内容的用户)的聚合。