CodePull
CodePull

Reputation: 290

NodeJS With Mongo: Callback Is Not A Function error

Im currently working on a NodeJS/Mongo project where I need to pull all the documents from a collection. I currently have the following code written:

var Db = require('mongodb').Db,
    MongoClient = require('mongodb').MongoClient,
    Server = require('mongodb').Server,
    ReplSetServers = require('mongodb').ReplSetServers,
    ObjectID = require('mongodb').ObjectID,
    Binary = require('mongodb').Binary,
    GridStore = require('mongodb').GridStore,
    Grid = require('mongodb').Grid,
    Code = require('mongodb').Code,
    assert = require('assert');

var server = new Server('[server]', 27017);

var authDB = new Db('admin', server);
var DB1250 = new Db('1250', server); 

var findDocuments = function (callback) {
    authDB.authenticate("Username", "Password");
    DB1250.open(function (error, db) {
        if (error) {
            console.log(error);
        }
        else {
            console.log("successfully accessed: ", db);
            callback;
            var cursor = db.collection('Patients').find();
            console.log('cursor ', cursor);
            cursor.forEach(function (error, document) {
                if (error) {
                    console.log('Document does not exist. Error: ', error);
                }
                else {                        
                    console.log('Document: ', document);
                }
            });
        }
    });
};

findDocuments(function (data) {

});

I am able to authenticate/connect to the server, connect to the DB, and connect to the collection. When I enter the forEach loop to iterate through all the documents, I keep getting the error "Callback is not a function". Can you guys see what I am doing wrong?

Upvotes: 0

Views: 1436

Answers (3)

Redu
Redu

Reputation: 26161

cursor.forEach() is an asynchronous operation but returns nothing. So you shouldn't do db.close() or likewise below the line somethere synchronously.

Besides; I am not sure which version Node driver you are refering to but in the recent ones like v3+ cursor.forEach() doesn't take an error first type callback like the one that you use in your code. It will take an "iterator" and an "end" callback such as;

cursor.forEach(doc => console.log(doc),
               err => err ? console.log(err)
                          : db.close())

So the above code will just work fine, iterating and processing the documents one by one as they appear without waiting up until all of them have been retrieved to the memory.

Upvotes: 0

CodePull
CodePull

Reputation: 290

Heres the solution I came up with after using Mongoose:

var Db = require('mongodb').Db,
    MongoClient = require('mongodb').MongoClient,
    Server = require('mongodb').Server,
    ReplSetServers = require('mongodb').ReplSetServers,
    ObjectID = require('mongodb').ObjectID,
    Binary = require('mongodb').Binary,
    GridStore = require('mongodb').GridStore,
    Grid = require('mongodb').Grid,
    Code = require('mongodb').Code,
    Mongoose = require('mongoose'); 
    assert = require('assert');    

var findDocuments = function (callback) {
    var options = { server: { socketOptions: { keepAlive: 1000 } } };

    var connectionString = 'mongodb://username:password@server:27017/admin';

    // Connected handler
    Mongoose.connect(connectionString, function (err) {

        var db = Mongoose.connection.useDb('db'); 
        var collection = db.collection("collection");           

        collection.find().stream()
            .on('data', function (document) {
                console.log(document);
            })
            .on('error', function (err) {
                // handle error
                console.log(err);
            })
            .on('end', function () {
                // final callback
            });
    });

    // Error handler
    Mongoose.connection.on('error', function (err) {
        console.log(err);
    });

    // Reconnect when closed
    Mongoose.connection.on('disconnected', function () {
        self.connectToDatabase();
    });

};

findDocuments(function () {
    db.close();
});

Upvotes: 0

broguinn
broguinn

Reputation: 591

I believe the cursor you have there has not resolved into an array, so forEach is not a valid method. You might be looking for eachAsync, which will wait for the query to return before iterating.

Alternatively, you can wait for the query promise to resolve, ie:

cursor.then(docs => docs.forEach(callback));

which I personally find a little clearer.

Upvotes: 1

Related Questions