4

I have a number of records stored in a MongoDB I'm trying to output them to the browser window by way of a Node.JS http server. I think I'm a good portion of the way along but I'm missing a few little things that are keeping it from actually working.

The code below uses node-mongo-native to connect to the database.

If there is anyone around who can help me make those last few connections with working in node I'd really appreciate it. To be fair, I'm sure this is just the start.

var sys  = require("sys");
var test = require("assert");
var http = require('http');

var     Db              = require('../lib/mongodb').Db,
        Connection      = require('../lib/mongodb').Connection,
        Server          = require('../lib/mongodb').Server,
        //BSON          = require('../lib/mongodb').BSONPure;
        BSON            = require('../lib/mongodb').BSONNative;

var     host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost';
var     port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : Connection.DEFAULT_PORT;

sys.puts("Connecting to " + host + ":" + port);

function PutItem(err, item){
    var result = "";
    if(item != null) {
            for (key in item) {
                    result += key + '=' + item[key];
            }
    }
    // sys.puts(sys.inspect(item))  // debug output
    return result;
}

function ReadTest(){
    var db = new Db('mydb', new Server(host, port, {}), {native_parser:true});
    var result = "";
    db.open(function (err, db) {
            db.collection('test', function(err, collection) {
                    collection.find(function (err, cursor){
                            cursor.each( function (err, item) {
                                    result += PutItem(err, item);
                            });
                    });
            });
    });
    return result;
}

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end("foo"+ReadTest());
}).listen(8124);
console.log('Server running on 8124');

Sources: - mongo connectivity code: https://github.com/christkv/node-mongodb-native/blob/master/examples/simple.js - node. http code: nodejs.org

EDIT CORRECTED CODE

Thanks to Mic below who got me rolling in the right direction. For anyone interested, the corrected solution is here:

function ReadTest(res){
    var db = new Db('mydb', new Server(host, port, {}), {native_parser:true});
    var result = "";
    res.write("in readtest\n");
    db.open(function (err, db) {
            res.write("now open\n");
            db.collection('test', function(err, collection) {
                    res.write("in collection\n");
                    collection.find(function (err, cursor){
                            res.write("found\n");
                            cursor.each( function (err, item) {
                                    res.write("now open\n");
                                    var x = PutItem(err, item);
                                    sys.puts(x);
                                    res.write(x);
                                    if (item == null) {
                                            res.end('foo');
                                    }
                            });
                    });
            });
    });
}

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write("start\n");
    ReadTest(res);
}).listen(8124);
console.log('Server running on 8124');
Alex C
  • 16,624
  • 18
  • 66
  • 98
  • 1
    I assume the `err` in each of those function definitions is for an error status -- do any of them report an error? – sarnold Apr 02 '11 at 22:17
  • no errors, I've taken the connection code from someone on github, and the HTTP server from node's homepage. (added links to the question above) both code samples work on their own, additionally adding `sys.puts(sys.inspect(item))` in the `PutItem` function shows that I'm reading the database correctly. – Alex C Apr 02 '11 at 22:22
  • 1
    Are the calls to db blocking calls? If not, I presume result will actually be returned and written to your http response before it is populated by anything. – Mic Apr 02 '11 at 22:27
  • node-mongo-native is said to be non-blocking. so you might be right about that. I'm going to try to change the `res.end` for `res.write` and see if that works. Also think I'll have to pass the `res` into the ReadTest function. Will update if you're right. :) – Alex C Apr 02 '11 at 22:35
  • Have you tried a wrapper like mongoose? It should make the entire database connection simpler. – Raynos Apr 02 '11 at 23:04

4 Answers4

6

My guess is that you are returning result, writing the response, and closing the connection before anything is fetched from the db.

One solution would be to pass the response object to where you actually need it, something like:

function readTest(res) {
    db.open(function (err, db) {
        db.collection('test', function(err, collection) {
            collection.find(function (err, cursor) {
                res.writeHead(200, {'Content-type' : 'text/plain'});
                cursor.each( function (err, item) { res.write(item); });
                res.end();
     ...

Of course, you should also handle errors and try to avoid nesting too many levels, but that's a different discussion.

Mic
  • 6,741
  • 3
  • 24
  • 25
  • Sadly, that didn't work. Something's still missing. **edit** I double checked and have found that string data is correctly returning from PutItem. there may be a few things I can still try along this line. – Alex C Apr 02 '11 at 22:48
  • 1
    Just to be on the safe side, you removed 'res.end("foo"+ReadTest());' right? The only res.end should be in the readtest function. And are you getting anything at all, like an exception or an error? – Mic Apr 02 '11 at 22:57
  • ... hold on... making progress with this line of questioning. you might still be right :) – Alex C Apr 02 '11 at 22:59
  • YES! you were right. I will update the original post with the corrected code so anyone interested can see – Alex C Apr 02 '11 at 23:08
1

Instead of writing all the low-level Mongodb access code, you might want to try a simple library like mongous so that you can focus on your data, not on MongoDB quirks.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
1

You might want to try mongoskin too.

guilin 桂林
  • 17,050
  • 29
  • 92
  • 146
0

Reading documents

To apply specific value filters, we can pass specific values to the find() command. Here is a SQL query:

SELECT * FROM Table1 WHERE name = 'ABC'

which is equivalent to the following in MongoDB (notice Collection1 for Table1):

db.Collection1.find({name: 'ABC'})

We can chain count() to get the number of results, pretty() to get a readable result. The results can be further narrowed by adding additional parameters:

db.Collection1.find({name: 'ABC', rollNo: 5})

It's important to notice that these filters are ANDed together, by default. To apply an OR filter, we need to use $or. These filters will be specified depending upon the structure of the document. Ex: for object attribute name for an object school, we need to specify filter like "school.name" = 'AUHS'

We're using here the DOT notation, by trying to access a nested field name of a field school. Also notice that the filters are quoted, without which we'll get syntax errors.

Equality matches on arrays can be performed:

  • on the entire arrays
  • based on any element
  • based on a specific element
  • more complex matches using operators

In the below query:

db.Collection1.find({name: ['ABC','XYZ']})

MongoDB is going to identify documents by an exact match to an array of one or more values. Now for these types of queries, the order of elements matters, meaning that we will only match documents that have ABC followed by XYZ and those are the only 2 elements of the array name


{name:["ABC","GHI","XYZ"]},
{name:["DEF","ABC","XYZ"]}

In the above document, let's say that we need to get all the documnts where ABC is the first element. So, we'll use the below filter:

db.Schools.find({'name.0': 'ABC' })

Zameer Ansari
  • 28,977
  • 24
  • 140
  • 219