0
var asynclib = require('async');

exports.apiFindNutrients = function(req, res) {
    var ndb = req.params.ndb;

    NutrDefModel.find().limit(30).exec(function(error, nutref) {

            asynclib.mapSeries(nutref, function(ref, callback) {

              NutrModel.find({ Nutr_No: ref.Nutr_No, Ndb_No: ndb }, function(error, nutrient) {

                  console.log(nutrient + 'nutrval: ' + nutrient.Nutr_Val);
                  var result = {
                      Ndb_No: nutrient.Ndb_No,
                      Nutr_No: ref.Nutr_No,
                      Units: ref.Units,
                      Tagname: ref.Tagname,
                      Nutr_Desc: ref.Nutr_Desc,
                      Nutr_Val: nutrient.Nutr_Val
                  };


                      callback(null, result);
                  }
              });

            }, function (err, result) {
                if (err)
                    console.log('async lib ' + err);
                res.send(result);
            });

        }
    });

};

I want to join two tables with mongoose, i came up with the above solution but it takes 12 seconds for 70 items in NutrDefModel, when i do limit(30) it takes 1.5 seconds. I need to improve to under 1 seconds. I am really new to async javascript and mongoose, i barely understand how async library works in this solution, what alternetives do i have with javascript and mongoose.

I've added some indexes it improved performance, but now i have another problem. Above console.log line produces the output:

{ Ndb_No: 3198,
  Nutr_No: 318,
  Nutr_Val: '144',
  _id: 5222665eab19d2db1800379d }nutrval: undefined

you can see nutrition object contains Nutr_Val but nutrient.Nutr_Val prints undefined. Why?

  • You've designed your schemas poorly if you need to Join tables with Mongodb as it doesn't support them efficiently. You'll need to rethink your design. – WiredPrairie Sep 01 '13 at 12:09
  • I've added some indexes and it works faster but now i have another problem, see edit above. –  Sep 01 '13 at 12:59
  • Your field name is spelled differently. It must be exact. Case matters. – WiredPrairie Sep 01 '13 at 14:22
  • Spelling is correct, i checked it many times. I found a similar problem here, but in my case console.log(typeof nutrient) yields object i don't know how to fix it :( http://stackoverflow.com/questions/7922226/why-is-this-object-property-undefined –  Sep 01 '13 at 14:26
  • What are you actually typing to see the value? `nutrval` is not the same as `Nutr_Val`. – WiredPrairie Sep 01 '13 at 14:32
  • nutrition.Nutr_Val == undefined?? i think i cannot fix this problem easily, can you provide me a way to join two documents by some field. i don't use ref keyword but its a reference. –  Sep 01 '13 at 14:37

1 Answers1

2

I would recommend against trying to do a join with MongoDB and would instead investigate options for adjusting your schema and collections to better fit with your query requirements.

The issue you're seeing is that the find method returns an array (docs for query). If you know there is only a single/exact result, I'd recommend you use findOne instead.

NutrModel.find({ Nutr_No: ref.Nutr_No, Ndb_No: ndb }, function(error, nutrient) {
     if (err) { console.log('error!'); return; }
     console.log("count: " + nutrient.length);
     for(var i=0, len=nutrient.length; i < length; i++) {
        var onenutrient = nutrient[i];
        // now, do something ...
     } 
     callback(null, result);
   }
);

Or, just

NutrModel.findOne({ Nutr_No: ref.Nutr_No, Ndb_No: ndb }, function(error, nutrient) {
    if (err) { console.log('error!'); return; }
    // do something with the nutrient
} 
WiredPrairie
  • 58,954
  • 17
  • 116
  • 143