Sorry if the title itself is a contradiction :) JS beginner here..
I get an array of MongoDB documents and I want to extend each one with another object (from another table) so that I can pass this array of extended objects to my view. I want to achieve something like this:
exports.myFunction = function(req, res) {
Book.find({'good': true}).exec(function(err, docs) { // find good books
// add authors to each book (?):
for (var i = 0, i < docs.length; i++) {
docs[i].author = Author.findOne({'_id': docs[i].author_id});
}
// render books:
res.render('/books.ejs', {books: docs});
});
}
I think this is not the JavaScript-way to do it :) So how can I achieve this?
Thanks,
Use the $lookup function as found in the aggregation framework. The following example demonstrates how you can apply that in your case:
exports.myFunction = function(req, res) {
Book.aggregate([
{ "$match": { "good": true } },
{
"$lookup": {
"from": "authors"
"localField": "author_id",
"foreignField": "_id",
"as": "author"
}
},
{ "$unwind": "author" }
]).exec(function(err, docs) {
res.render('/books.ejs', {books: docs});
});
}
I found another solution, which is using populate.
For this, I needed to change my Book model,
from:
var mongoose = require('mongoose');
var bookSchema = mongoose.Schema({
author_id: String,
good: Boolean
});
to:
var mongoose = require('mongoose');
var Author = require('./author.js'); // added this
var bookSchema = mongoose.Schema({
author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' },
good: Boolean
});
And I chain populate() to my initial query as follows:
exports.myFunction = function(req, res) {
Book.find({'good': true}).populate('author').exec(function(err, docs) { // find good books
// render books:
res.render('/books.ejs', {books: docs});
});
}