简体   繁体   中英

Rendering view with all the data using jade,express and monk

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?

EDIT Error when using async:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM