将mongoose的查询结果存储在另一个mongoose查询中

我对nodeJs和mongodb相当陌生。 我在查询mongoose物品时遇到了一些问题。 我有2个模型

用户型号:

var mongoose = require('mongoose'); var bcrypt = require('bcrypt'); var gravatar = require('gravatar'); var Schema = mongoose.Schema; var SendSchema = require('./Send').schema; var TravelSchema = require('./Travel').schema; var UserSchema = new Schema({ name: String, email:{type: String, required: true, unique:true}, phone: {type: String, required: true, unique:true}, password: {type:String,required:true}, token: String, is_admin : Boolean, sendings : [SendSchema], travels : [TravelSchema], created_at : Date, updated_at : Date, image_url: String }) UserSchema.pre('save',function(next){ var user = this; if (this.isModified('password')||this.isNew){ bcrypt.genSalt(10,function(err,salt){ if(err){ return next(err); } bcrypt.hash(user.password,salt,function(err,hash){ if(err){ return next(err); } user.password = hash; next(); }); }); } else { return next(); } }); UserSchema.pre('save', function(next) { var currentDate = new Date(); this.updated_at = currentDate; if (!this.created_at) this.created_at = currentDate; next(); }); UserSchema.methods.comparePassword = function (pw,cb) { bcrypt.compare(pw,this.password,function(err,isMatch){ if(err){ return cb(err); } cb(null,isMatch); }); }; module.exports = mongoose.model('User',UserSchema); 

和旅行模式:

 var mongoose = require('mongoose'); var Schema = mongoose.Schema; var TravelSchema = new Schema({ travelling_from:String, travelling_to:String, amount:String, date:Date, created_at: Date, updated_at: Date, traveller : {type:Schema.Types.ObjectId ,ref:'User'} }); TravelSchema.pre('save', function(next) { var currentDate = new Date(); this.updated_at = currentDate; if (!this.created_at) this.created_at = currentDate; next(); }); module.exports = mongoose.model('Travel',TravelSchema); 

现在使用快速路线我正在查询这样的mongoose模型:

 router.post('/travellers',passport.authenticate('jwt',{session:false}), function(req, res, next) { var pickup_location = req.body.pickup_location; var delivery_location = req.body.delivery_location; var date = req.body.date; var sender = req.user._id; var senders = []; var travellers =[]; Travel.find({'date':date},function (err,travels) { if(err) console.error(err.message);; async.forEach(travels,function (travel,callback) { User.findById(travel.traveller,function (err,user) { if(err) throw err; data = { name:user.name, email:user.email, phone:user.phone, image_url:user.image_url, type:'traveller' }; console.log(data); travellers.push(data); callback(); }); },function (err) { if(err) console.error(err.message);; }); }); console.log(travellers); res.json(travellers); }); 

当我尝试访问res.json()后查询旅客数组查询完成时,我得到一个空的回应,而当我console.log()的数据它正确打印在查询期间,有人可以帮助我通过这个新asynchronous的范例,我已经敲了我的头2天了。

添加将一次运行一个函数的async.series API,等待它调用其任务callback,最后当所有任务完成时,将运行callback (最终callback)。

例如:

 router.post('/travellers', passport.authenticate('jwt', { "session": false }), function(req, res, next) { var pickup_location = req.body.pickup_location; var delivery_location = req.body.delivery_location; var date = req.body.date; var sender = req.user._id; var locals = { travellers: [], senders: [] }; async.series([ // Load travels first function(callback) { Travel.find({ "date": date }, function (err, travels) { if (err) return callback(err); locals.travels = travels; callback(); }); }, // Load users (won't be called before task 1's "task callback" has been called) function(callback) { async.forEach(locals.travels, function (travel, callback) { User.findById(travel.traveller, function (err, user) { if (err) return callback(err); data = { "name": user.name, "email": user.email, "phone": user.phone, "image_url": user.image_url, "type": "traveller" }; console.log(data); local.travellers.push(data); callback(); }); }, function (err) { if (err) return callback(err); callback(); }); } ], function(err) { /* This function gets called after the two tasks have called their "task callbacks" */ if (err) return next(err); //Here locals will be populated with `travellers` and `senders` //Just like in the previous example console.log(locals); console.log(locals.travellers); res.json(locals.travellers); }); }); 

另一种方法是在聚合框架中使用$lookup操作符,您可以在其中运行聚合操作,如下所示:

 router.post('/travellers', passport.authenticate('jwt', {session: false }), function(req, res, next) { var pickup_location = req.body.pickup_location; var delivery_location = req.body.delivery_location; var date = req.body.date; Travel.aggregate([ { "$match": { "date": date } }, { "$lookup": { "from": "users", "localField": "traveller", "foreignField": "_id", "as": "traveller" } }, { "$unwind": "$traveller" }, { "$group": { "_id": null, "travellers": { "$push": { "name": "$traveller.name", "email": "$traveller.email", "phone": "$traveller.phone", "image_url": "$traveller.image_url", "type": "traveller" } } } } ], function(err, results) { if (err) return next(err); console.log(results); console.log(results[0].travellers); res.json(locals[0].travellers); }); });