0

I am trying to read from MongoDB and print the contents to a webpage. I am using mongodb module to read from Mongo.

I am able to successfully read and print the data to a webpage but I am not able to figure out when to close the db and when to end the http connection. Hence my webpage prints results but keeps waiting for the server to send something.

I referred the following questions but can't understand what I need to do in this specific scenario:

Here is my code:

/* Opens the secondary collection and goes through each entry*/
var getClientIDs = function(collect, res) {
  db.collection(collect, function(err, collection) {

      var cursor = collection.find();

      cursor.each(function(err, item) {
            if(item != null) {          
            console.log(item['_id'] +"\t" + item['name']);
            res.write(item['_id'].toString());
            res.write("  ");
            res.write(item['name'].toString());
            res.write("</br>");
            }
            /*else {
                res.end("The End"); 
                db.close();     
            } Closes connection before other stuff is done. */
      });
    });

}
/* Opens the main collection and goes through each entry*/
var openCollection = function(collect, res) {
    console.log(green);
    // Establish connection to db
    db.open(function(err, db) {

      // Open a collection
      db.collection(collect, function(err, collection) {

          // Create a cursor
          var cursor = collection.find();

          // Execute the each command, triggers for each document
          cursor.each(function(err, item) {
                if(item != null) {
                getClientIDs(item['_id'], res);
                }
                /* else {
                    db.close();
              }   This closes the connection before other stuff is done */
          });
        });
      });
}
/* Start Here */ 
var http = require('http');
var port = 8888;
http.createServer(function (req, res) {
    res.writeHead(200,{"Content-Type": "text/html; charset=utf-8"});
    openCollection('company',res);
}).listen(port);

The way the db is that there is a collection called 'company' and it has a bunch of IDs in it. There are other collections with the name of the id :

company   = {{ _id: 'A001' }
             { _id: 'A002' }
             { _id: 'A003' }
            }      
A001 = {{_id: "A001-01", "name":"foo"}  
        {_id: "A001-02", "name":"bar"}}

A002 = {{_id: "A002-01", "name":"foo2"}  
        {_id: "A002-02", "name":"bar2"}}

I did not create the collections this way. This was what I had to work with and create a script which would just print IDs and names on a webpage.

With my code, the webpage prints:

A001-01    foo
A001-02    bar
A002-01    foo2
A002-02    bar2

Thank you.

Community
  • 1
  • 1
Bharat
  • 2,960
  • 2
  • 38
  • 57

1 Answers1

1

When you open a MongoDB connection with the native driver, you're actually opening a pool of 5 connections (by default). So it's best to open that pool when your app starts and just leave it open rather than open and close the pool on each request.

You're on the right track with closing out your HTTP response; just call res.end(); when the response is complete (i.e. when item is null in the cursor.each callback).

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • I tired adding res.end() in the case when item==null but that does not print anything on the webpage. Though my console.log() prints the entries. So it looks like res.end() happens before the items are fetched from the DB. – Bharat Nov 16 '12 at 21:26
  • And also, if I don't close the db connection and refresh the browser, it says `Error: db object already connecting, open cannot be called multiple times` – Bharat Nov 16 '12 at 21:28
  • I hacked a fix for the db closing error on page refresh. I added a `db.close()` inside `http.createServer()`. Each time the page is refreshed, this method is called and it closes the db connection before passing the buck to `openCollection()`. Still need to figure out closing the http connection. – Bharat Nov 16 '12 at 21:50
  • Added another hack in. I made the page timeout after 10 seconds using `res.connection.setTimeout(10000)`, thus not making my browser keep waiting for ever. These hackish fixes aren't the best thing to do :( – Bharat Nov 16 '12 at 22:07
  • @RBK I didn't mean that should leave your code as is and just not close the db connection, I meant that you should move opening the db pool to your app startup, prior to the `listen` call. I took a closer look at the rest of your code and I don't understand why you're iterating over the collection in `openConnection` and then again in `getClientIDs` for each item in the collection. That's why your `res.end()` call isn't working as expected. – JohnnyHK Nov 16 '12 at 22:12
  • Oh ok. So I will move the db connection call to the start of the app. Will try that out. In openConnection() I am trying to go over the `company` collection(described at the end of my question) and I am getting each id from it and then in `getClientIDs `, I am opening and iterating over collections with the names got by iterating over the company collection. I could have had it in the same method but I din't want to make it look cluttered considering I am new to node and wanted avoid confusing myself. :) – Bharat Nov 16 '12 at 22:32