2

I am very new to MEAN stack and i am trying to learn async.

I'm trying to combine two collections from the mongodb using async

and applied this iterate over a collection, perform an async task for each item, i'm a trying to learn the simplest and efficient way of doing this simple tasks so it will be easy to understand.

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 }

}

Payment Model

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

Here is my 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)
        });

})

I am expecting to receive a JSON Object like this, but i'm getting is undefined.

[{ 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 }
},...]

Please comment if you need more clarification or something is missing. Thank you! Cheers!

2
  • async.forEach callback does not provide data, you should use aysnc.map caolan.github.io/async/docs.html#each Commented Dec 6, 2016 at 8:58
  • i tried storing data from the query into a local variable, so that if the tasks are finished response data will be the local variable. is that correct? Commented Dec 6, 2016 at 9:18

1 Answer 1

1

The simplest and most efficient way of doing this simple task is by using the aggregation framework where you can leverage mongo's native operators like $match to filter the document stream to allow only matching documents to pass unmodified into the next pipeline stage and $lookup to perform a left outer join to the payment collection in the same database to filter in documents from the "joined" collection for processing:

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

However, as it stands your code is failing here

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

since vorders object does not have any id key but _id, so that should be

PaymentModel.find({ "order_id": vorders._id }, function(err, payments){
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! does order_id: "id" or order_id: ObjectId("id") make a difference? I can't make to seem it work. :)
this answer is really straightforward and simple, i don't need to work with async to reach my requirement
You don't necessarily need to cast a string to ObjectIdin Mongoose as it does this implicitly for you ("behind the scenes")
I see, i'm trying to implement your code, but i still get undefined. im not sure what to put with "from" in $lookup. i posted more details about the model and how it is required.
so, it didn't worked because of the error. i didn't see the error until i debugged it in the browser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.