My mongodb
database has two collections notes
which holds each note and notebook
which has a title and an array of notes
containing an array
of id
s pointing to the note
in the notes
collection.
//notes:
{
"_id" : ObjectId("542afaaa4898f4042312872b"),
"title" : "Hello Universe",
"content" : "Saving to database"
}
//notebook
{
"_id" : ObjectId("53d0c6d8daeac43cf8412945"),
"title" : "My Notebook",
"notes" : [
ObjectId("53d0ca2fdaeac43cf8412946"),
ObjectId("542afe34a25e3c44160e6b05"),
ObjectId("542b7908a459766020342eae"),
ObjectId("542b79efa459766020342eaf"),
ObjectId("542b7a5ba459766020342eb0"),
ObjectId("542b7aa3d3b135c022b674ff"),
ObjectId("542bb47aa4ff29c820c22fdc"),
ObjectId("542bb720a4ff29c820c22fdd"),
ObjectId("542bddd5712c0dc426d41341"),
ObjectId("542bdec5712c0dc426d41342")
]
}
I use these to retrieve data to render this jade
view .This is the code for my route
:
router.get('/main',function(req,res){
var db=req.db;
var notebookCollection=db.get('notebook');
var notesCollection=db.get('notes');
var locals={};
locals.title="TakeNote:An easy to use note taking app for web and hopefully mobile";
locals.sidebar={};
locals.sidebar.items=[];
//get data for the first notebook and display it by default
locals.notebook={};
locals.notebook.notes=[];
notebookCollection.find({},{},function(err,docs){
if(err)
console.error(err);
else
{
console.log("Retrieving notebooks");
var noteIds;
if(docs.length)
{
console.log(docs)
for(var i=0;i<docs.length;i++)
{
locals.sidebar.items.push(docs[i].title);
locals.notebook.title=docs[i].title;
noteIds=docs[i].notes;
for(var j=0;j<noteIds.length;j++)
{
notesCollection.findOne({_id:noteIds[j]},function(err,doc){
if(err)
console.error(err);
else
{
locals.notebook.notes.push(doc);
//res.render('main',locals);
}
});
//putting it here might mean that it renders without any of the notes
//putting it here with a condition fails
/*
if(j===noteIds.length-1)
res.render('main',locals);
*/
}
}
//putting it here means it renders without any of the notes
}
}
});
});
Where can I call res.render('main',locals)
so that it renders the template with all my data here?
I get this error when using the async
library:
E:\Do\hello_express\node_notes\node_modules\async\lib\async.js:641
tasks[index].apply(null, arguments);
^
TypeError: Object #<Promise> has no method 'apply'
at fn (E:\Do\hello_express\node_notes\node_modules\async\lib\async.js:641:34
)
at Object._onImmediate (E:\Do\hello_express\node_notes\node_modules\async\li
b\async.js:557:34)
at processImmediate [as _immediateCallback] (timers.js:336:15)
\
npm ERR! node_notes@0.0.1 start: `node ./bin/www`
npm ERR! Exit status 8
npm ERR!
npm ERR! Failed at the node_notes@0.0.1 start script.
npm ERR! This is most likely a problem with the node_notes package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node ./bin/www
npm ERR! You can get their info via:
npm ERR! npm owner ls node_notes
npm ERR! There is likely additional logging output above.
npm ERR! System Windows_NT 6.1.7600
npm ERR! command "C:\\Program Files\\nodejs\\\\node.exe" "C:\\Program Files\\nod
ejs\\node_modules\\npm\\bin\\npm-cli.js" "start"
npm ERR! cwd E:\Do\hello_express\node_notes
npm ERR! node -v v0.10.29
npm ERR! npm -v 1.4.14
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! E:\Do\hello_express\node_notes\npm-debug.log
npm ERR! not ok code 0
This is my async code:
function getActiveNotes(doc)
{
var noteIds=doc.notes;
async.map(noteIds,function(_id){
notesCollection.findOne({_id:_id})
},function(err,docs){
if(err)
console.error(err);
else
{
if(docs)
locals.notebook.notes=docs;
}
});
}
function getAllNotebooks()
{
notebookCollection.find({},{},function(err,docs){
if(err)
console.error(err);
else
{
if(docs)
{
for(var i=0;i<docs.length;i++)
{
locals.sidebar.items.push(docs[i].title);
}
}
}
});
}
function activeNotesOp(){
async.waterfall([notebookCollection.findOne({isActive:true}),getActiveNotes]);
}
async.parallel([getAllNotebooks,activeNotesOp],function(err,results){
if(err)
console.error(err);
else
console.log(results);
});
On reflection parallel
may not be what you need, but I think this is a useful skeleton for you.
var notebooksIdx = 0;
notebookCollection.find({},{},function(err,notebooks){
async.each(
notebooks,
, function(notebook, cb) {
notesCollection.find({_id: {$in: notebook.notes}}, function(err, notes) {
if (err)
return cb(err);
return locals.notebook[notebooksIdx++].notes = notes;
})
}
, function(err) {
if (err) throw err;
res.render(....)
}
});
});
I used lodash
method forEach
to obtain the title of each notebook
to populate the locals.sidebar
,I used lodash.filter
(this returns an array,obtained the first item) to find the activeNotebook
and retrieve all the notes from it using the $in
operator to perform a query for all the notes contained by the notebook and populated locals.notebook.notes
with that data:
notebookCollection.find({},{},function(err,notebooks){
if(err)
console.error(err);
else
{
_(notebooks).forEach(function(notebook){
locals.sidebar.items.push(notebook.title);
});
//console.log(locals.sidebar.items);
var activeNotebooks= _.filter(notebooks,function(notebook){
return notebook.isActive;
});
var notes=activeNotebooks[0].notes;
notesCollection.find({_id:{$in:notes}},function(err,docs){
if(err)
console.error(err);
else
{
if(docs.length)
{
locals.notebook.notes=docs;
console.dir(locals);
res.render('main',locals);
}
}
});
}
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.