2016-12-22 14 views
2

私はかなり新しいnodeJsとmongodbです。 mongooseオブジェクトのクエリに関するいくつかの問題がありました。私が持っている2機種mongooseクエリの結果を他のmongooseクエリに格納

Userモデル:

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); 

今使って明示ルート私はこのようなマングースモデルを照会しています:

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()の後に旅行者の配列にアクセスしようとすると、私は空のrespを取得するクエリが完了です一方、私がconsole.log()のデータを照会している間に正しく印刷されると、誰かがこの新しい非同期パラダイムを通して私を助けてくれますか?私は2日間頭を叩いています。

+0

'のRES:

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演算子を使用することです.json'は 'async.forEach'コールバックに入っていなければなりません。しかし、ユーザーがTravelの 'traveller'プロパティに入っているので、参照集団を使ってこれをもっと簡単に解決できると思います。 OT:なぜこのメソッドは 'POST'ですか?あなたは明らかにデータを変更していませんか? – qqilihq

+0

投稿要求に存在する日付プロパティからデータを取得する必要があるため、私は投稿を使用しています。 –

答えて

1

一度に1つの関数を実行し、タスクコールバックを呼び出すのを待ってから最後にすべてのタスクが完了するとcallback(最終コールバック)を実行するAPIを追加します。例えば

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); 
    }); 
}); 
+1

私はあなたの答えによってそれを1回の変更で完了できました async.foreach()関数の 'function(err)'に 'callback()'を追加する必要があります。 –

+0

@VedantRathoreいいです。私は不足している 'callback()'を追加しました。 – chridam

関連する問題