0
votes

I'm trying to get mongoose populate to work.

I have two models one for orders and the other for the order items.

I'm doing this purely to understand populate.

I did have two files for this but I have now got everything in one file called main.js

main.js creates the 3 items in items model.

I then try to populate the order model with the 3 items.

Output for the query now gives the correct populated result.

That is to say the output from the line

console.log(JSON.stringify(orders, null, "\t");

is now:

[ { "_id": "55d32e4594db780b1bbb4372", "__v": 0, "lines": [ { "price": 2.4, "quantity": 5, "_id": "55d32e4594db780b1bbb436f", "__v": 0 }, { "price": 3.7, "quantity": 7, "_id": "55d32e4594db780b1bbb4370", "__v": 0 }, { "price": 1.2, "quantity": 3, "_id": "55d32e4594db780b1bbb4371", "__v": 0 } ] } ]

The database however is not populating.

Below is the main.js file

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydb');

var Schema = mongoose.Schema;

var OrderSchema = new Schema({
  lines: [{type: mongoose.Schema.Types.ObjectId, ref: 'Item'}]
});

var ItemSchema = new Schema({
  price: Number,
  quantity: Number
});

var Order = mongoose.model('Order', OrderSchema);
var Item = mongoose.model('Item', ItemSchema);

var itemArray = [
  {price: 2.4, quantity: 5},
  {price: 3.7, quantity: 7},
  {price: 1.2, quantity: 3}
];

Item.create(itemArray, function(err) {
  if (err) {
    console.log('Error creating items: ', err);
  }

  var order = new Order();
    Item.find({}, {_id: 1}, function(err, result) {
        result.forEach(function(obj) {
                order.lines.push(obj._id);
        });
    }).exec().then(function() {
        order.save(function(err) {
            if (!err) {
                Order.find({})
                    .populate('lines')
                    .exec(function(err, orders) {
                        console.log(JSON.stringify(orders, null, "\t")); // output is populated the database is still not populating.

                    });
            }
        });
}    );
});
1
So you do realize you need to add the items to the order first? The .populate() call just pulls in the already attached item data as first class objects and not references. You seem to be expecting that it is just going to somehow "magically" add the items in. - Blakes Seven
Thank you for your reply Blakes Seven could you explain in more detail how I can get the 3 items I created with Item.create in main.js to populate the order I created in populate.js - Laurence
Not sure how more plain I can be about this. populate() does not add items to your object. There are pretty clear examples in the mongoose documentation. - Blakes Seven
Thank you for getting back to me Blakes Seven. I came across an example that I found works at "alexanderzeitler.com/articles/…". Also I now this working as I expect as output for the line console.log(JSON.stringify(orders, null, "\t")) - Laurence
The database is still not updating. Blakes Seven if you know how to fix my program could you please show some code to demonstrate what you are saying. - Laurence

1 Answers

0
votes

It appears there is some confusion for what the populate method is for. Essentially populate is mongoose's version of a "join". It allows a query (or a document) to automatically retrieve and "join" any associated documents and returns the modified document(s). Under the hood for every referenced value in a document that is to be populated, the populate method will execute a separate query to fetch those associated documents (generally this is by ID but can be a custom query) and then in memory it will replace the references with the retrieved documents.

It does not alter the documents in the collection at all as this is purely a fetch operation.