简体   繁体   中英

GET from 2 different MongoDB collections using MongoJS

I am using MongoJS to fetch data from mongo db in the following way: app.js:

var db = mongojs('db', ['events']);

And then:

   app.get('/', function(req, res){
    db.events.find(function(err,docs){
        res.render('index', {
        title: 'Events',
        events: docs
    });
    })  
});

This method works, I then fetch it using ejs as the view engine the following way: index.ejs:

<% events.forEach(function(event){ %>

<a><%= event.event_name %></a></br>
<a><%= event.event_description %></a> 

<% }) %>

This all works, however, How could I grab data from a different collection in the same ejs page? I've been trying to do it the following way: app.js: edited into

var db = mongojs('db', ['events', 'groups']);

And then:

app.get('/', function(req, res){
        db.events.find(function(err,docs){
            res.render('index', {
            title: 'Events',
            events: docs
        });
        })  
    });


       app.get('/', function(req, res){
        db.groups.find(function(err,docs){
            res.render('index', {
            title: 'Groups',
            groups: docs
        });
        })  
    });

Followed by the EJS:

<% groups.forEach(function(group){ %>

            <p><a><%= group.group_name %></a></br>
            <a><%= group.editor %></a></p>
            <a><%= group.members %></a></p>

 <% }) %>

The error that I'm getting is that 'groups' is not defined, however if I flip them like this inn app.js:

app.get('/', function(req, res){
            db.groups.find(function(err,docs){
                res.render('index', {
                title: 'Groups',
                groups: docs
            });
            })  
        });

app.get('/', function(req, res){
            db.events.find(function(err,docs){
                res.render('index', {
                title: 'Events',
                events: docs
            });
            })  
        });

Then it says events is not defined. How do I declare them both in one without one overwritting the other? If you can help with this, thank you so much.

You can only have one root app.get('/'... call. Try combining your routes like this:

app.get('/', function(req, res) {
    db.groups.find(function(groupsErr, groupDocs){

        // now get events
        db.events.find(function(eventsErr, eventDocs){
            res.render('index', {
                title: 'Events',
                events: eventDocs,
                groups: groupDocs
            });
        });
    });
});

You can also handle this in a slightly prettier fashion (less nested) using promises .

app.get('/', function(req, res) {
    let groupsPromise = new Promise((res, rej) => {
        db.groups.find((err, docs) => {
            if (!err) res(docs);
            else rej(err);
        });
    });

    let eventsPromise = new Promise((res, rej) => {
        db.events.find((err, docs) => {
            if (!err) res(docs);
            else rej(err);
        });
    });

    Promise.all([groupsPromise, eventsPromise])
    .then(docArr => {
        let groupDocs = docArr[0];
        let eventDocs = docArr[1];

        res.render('index', {
            title: 'Events',
            groups: groupDocs,
            events: eventDocs
        });
    })
    .catch(console.error);
});

After the first handler gets executed, the second one does not, so the simplest way is to chain your queries as:

let events;
app.get('/', function(req, res) {
db.events.find(function(err, docs) {
  events = docs;
  db.groups.find(function(err, docs) {
    res.render('index', {
      title: 'Items',
      groups: docs,
      events: events
    });
  })
});
})

The code above, couls be improved with the use of promises or async/await. I recommend you search about asynchronous functions for better programming in Javascript

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