2016-12-06 1 views
2

Je suis très nouveau à la pile MEAN et j'essaye d'apprendre async.Async: Combinant deux collection de mongodb using Async.forEach

J'essaie de combiner deux collections de la MongoDB en utilisant async

et appliqué cette iterate over a collection, perform an async task for each item, je suis essayer d'apprendre la façon la plus simple et efficace de faire des tâches simples de cette façon, il sera facile de comprendre .

var OrderSchema = new mongoose.Schema({ 

    menu_id: {type:mongoose.Schema.Types.ObjectId, ref: 'Foods'}, 
    menu_name: {type:String,required:false}, 
    customer_id: {type:String,required: true,}, 
    customer_name:{type:String, required: false}, 
    table_no:{type:String,required:true}, 
    cooking:{type:Boolean, require:false, default:false}, 
    ready:{type:Boolean,default:false}, 
    served:{type:Boolean,default:false}, 
    paid:{type:Boolean, default:false}, 
    price: {type:Number, default:0}, 
    quantity: {type:Number,default:0}, 
    created_at: { type: Date, default: Date.now } 

} 

Modèle de paiement

var mongoose = require('mongoose'); 

var PaymentSchema = new mongoose.Schema({ 
    order_number: {type:String, required: true, index: true}, 
    order_id: {type:mongoose.Schema.Types.ObjectId, ref: 'Orders'}, 
    date: { type: Date, default: Date.now }, 
    customer_id: {type:mongoose.Schema.Types.ObjectId, ref: 'User'}, 
    amount : { type: Number, required:true }, 
    company_id: {type:mongoose.Schema.Types.ObjectId, ref: 'Company'} 
}, 
{ 
    toJSON: { virtuals: true }, 
    toObject: { virtuals: true } 
}); 

module.exports = mongoose.model('Payments', PaymentSchema); 

Voici mon code

var data = req.body; 
var calls = []; 
var local_orders = []; 
var OrderModel = require('../models/Order'); 
var PaymentModel = require('../models/Payment'); 

OrderModel.find({'table_no': data.table_no}, function(err,orders){ 

    async.forEach(orders, function(vorders, callback){ 

     PaymentModel.find({order_id:vorders.id}, function(err, payments){ 
       vorders.payments = 'payments'; 
        local_orders.push(vorders) 
       }); 

       return callback(null, local_orders); 

      }, function(err,local_orders){ 
       if(err){ 
        res.status('500').send(err); 
       } 
       res.send(local_orders) 
     }); 

}) 

Je me attends à recevoir un objet comme ce JSON, mais je suis en train est indéfini.

[{ menu_id: {type:mongoose.Schema.Types.ObjectId, ref: 'Foods'}, 
    menu_name: {type:String,required:false}, 
    user_id: {type:String,required: true,}, 
    customer_name:{type:String, required: false}, 
    table_no:{type:String,required:true}, 
    cooking:{type:Boolean, require:false, default:false}, 
    ready:{type:Boolean,default:false}, 
    served:{type:Boolean,default:false}, 
    paid:{type:Boolean, default:false}, 
    price: {type:Number, default:0}, 
    quantity: {type:Number,default:0}, 
    created_at: { type: Date, default: Date.now }, 
    payments : [{ payment1 },{ payment2 } 
},...] 

S'il vous plaît commentaire si vous avez besoin plus de précisions ou quelque chose manque. Je vous remercie! À votre santé!

+0

rappel async.forEach ne fournit pas de données, vous devez utiliser aysnc.map http: // Caolan. github.io/async/docs.html#each – Dhirendra

+0

J'ai essayé de stocker des données de la requête dans une variable locale, de sorte que si les tâches sont terminées, les données de réponse seront la variable locale. Est-ce exact? –

Répondre

1

La façon la plus simple et la plus efficace de faire cette tâche simple est d'utiliser le cadre d'agrégation où vous pouvez tirer parti des opérateurs natifs de mongo comme $match pour filtrer le flux de documents pour permettre uniquement les documents correspondant à passer sans modification dans la phase suivante de pipeline et $lookup pour effectuer une jointure externe gauche à la collecte de paiement dans la même base de données pour filtrer dans les documents de la « joint » collection pour le traitement:

var data = req.body; 
OrderModel.aggregate([ 
    { "$match": { "table_no": data.table_no } }, 
    { 
     "$lookup": { 
      "from": "payments", 
      "localField": "_id", 
      "foreignField": "order_id", 
      "as": "payments" 
     } 
    } 
]).exec(function (err, result){ 
    if (err){ 
     res.status('500').send(err); 
    } 
    res.send(result) 
}); 

Cependant, tel qu'il est votre code échoue ici

PaymentModel.find({ order_id: vorders.id }, function(err, payments){ 

depuis vorders objet n'a pas de clé id mais _id, ce qui devrait être

PaymentModel.find({ "order_id": vorders._id }, function(err, payments){ 
+0

Merci! est-ce que order_id: "id" ou order_id: ObjectId ("id") fait une différence? Je ne peux pas faire sembler que ça marche. :) –

+0

cette réponse est vraiment simple et directe, je n'ai pas besoin de travailler avec async pour atteindre mon exigence –

+0

Vous n'avez pas nécessairement besoin de lancer une chaîne à 'ObjectId' dans Mongoose comme cela le fait implicitement pour vous (" dans les coulisses ") – chridam