connectivity to mongodb issue - node.js

I have the following code in a script.js file:
var express = require('express'),
app = express(),
cons = require('consolidate'),
MongoCl = require('mongodb').MongoClient,
Server = require('mongodb').Server;
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname +'/views');
var mongoclient = new MongoCl( new Server('localhost', 27017, {'native_parser' : true}));
var db = mongoclient.db('course');
app.get('/', function (req,res) {
db.collection('hello_mongo_express').findOne({}, function (err, doc) {
res.render('hello',doc);
});
});
app.get('*', function (req,res) {
res.send('Page not found',404);
});
mongoclient.open(function (err, mongoclient) {
if(err) throw err;
var port = 8080;
app.listen(port);
console.log("Express server started on port "+port);
});
./views/hello.html looks like :
<h1>Hello, {{name}}</h1>
I have a valid collection within a db 'course'.
When I try running using node, I face the following issue:
F:\mongo_proj>node script.js
F:\mongo_proj\script.js:11
var db = mongoclient.db('course');
^
TypeError: mongoclient.db is not a function
at Object.<anonymous> (F:\mongo_proj\script.js:11:22)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:968:3
Even though, I guess all the code that creates the mongoclient, db objects, will get called only when the db connectivity is been established. So what could the issue be
edit:
I tried #jerry's suggestion:

try this.. this simple way of connection
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
// Connection URL
var url = 'mongodb://localhost:27017/myproject';
// Use connect method to connect to the Server
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server");
db.close();
});
refer this link and try this
https://www.npmjs.com/package/mongodb

This issue is coming because, you are trying to use mongoclient before it opens connection. So wrap the code in open function as follow:
var db;
mongoclient.open(function (err, mongoclient) {
db = mongoclient.db('course');
if(err) throw err;
var port = 8080;
app.listen(port);
console.log("Express server started on port "+port);
});
See the link for further reference mongo connection
Also this .open() method is used in older versions. With newer version use .connect() method instead. For later versions may be refer this node driver manual

Related

Error when connecting to mongodb

I am using node-run-cmd package to start the mongodb server in my app.js file. I know this works because I can see the collections on Robomongo when my script is running as well as the mongod.exe in my list of running processes. The problem is trying to connect to the db called testDB. Below is the commented code.
//start mongodb server
//this works
var nrc = require('node-run-cmd');
var cmd = '..\\mongodb\\mongod --dbpath '+__dirname+'\\db';
nrc.run(cmd);
//setup
var express = require('express');
var MongoClient = require('mongodb').MongoClient;
var app = express();
app.use(express.static('public'));
app.set('view engine', 'ejs');
//connect to mongo
//this fails to connect to db testDB
var url = 'mongodb://localhost:27017/testDB';
MongoClient.connect(url, function(err, db) {
if(!err) {
console.log("connection successful");
}
else{
console.log(err.message)
}
});
Here is the err.message
failed to connect to server [localhost:27017] on first connect
Any idea what I am doing wrong here. My assumption is that the db connection is trying before the server has fully started but I am not completely sure.
EDIT:
so that's what it was, timing issue. I tried the following and it connected to the DB. Is there a graceful way of doing this other than what I have here?
function connect(){
var url = 'mongodb://localhost:27017/testDB';
MongoClient.connect(url, function(err, db) {
if (!err) {
console.log("connection successful");
}
else {
console.log(err.message)
}
});
}
setTimeout(connect, 10000);
You should use the callback in the node_run_cmd package (https://www.npmjs.com/package/node-run-cmd#callback-style).
Place your connect function inside the callback.
You will probably also want to only start express here as well.

Can not insert data into mongodalab collection

I just start use Node.JS , try to connect to MongodbLab , I follow the doc http://docs.mongolab.com/#connect
but can not insert any data in my collection "team" the error keep saying TypeError: Cannot read property 'insert' of undefined , I google for 2 hrs ,Help please.
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
var mongoose = require('mongoose');
var uri = "mongodb://awei:RRRRR#ds061365.mongolab.com:61365/aweitest";
mongoose.createConnection(uri);
// we're connected!
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection errrrrrrrror:'));
db.once('open', function() {
});
db.team.insert({ "name" : "Awei" });
error
c:\Users\awei\WebstormProjects\untitled\app.js:22
db.team.insert({ "name" : "Awei" });
^
TypeError: Cannot read property 'insert' of undefined
at Object.<anonymous> (c:\Users\awei\WebstormProjects\untitled\app.js:22:8)
at Module._compile (module.js:413:34)
at Object.Module._extensions..js (module.js:422:10)
at Module.load (module.js:357:32)
at Function.Module._load (module.js:314:12)
at Function.Module.runMain (module.js:447:10)
at startup (node.js:140:18)
at node.js:1001:3
Process finished with exit code 1
From what I am seeing, you need to connect with a username and password. See this:
http://docs.mongolab.com/connecting/
under "Finding your database connection info".
In addition, MongoLab offers getting-started help for Node.js here:
http://docs.mongolab.com/languages/
Once you are actually connected to the database, you should be able to insert data to the team collection.
You can access a pre-existing collection without the model using the mongoose connection's db object as follows:
var uri = "mongodb://awei:RRRRR#ds061365.mongolab.com:61365/aweitest";
mongoose.connect(uri);
var conn = mongoose.connection,
db = conn.db;
conn.on('error', console.error.bind(console, 'connection errrrrrrrror:'));
conn.on('open', function() {
console.log("mongodb is connected!!");
db.collection("team", function (err, collection) {
collection.insert({ "name" : "Awei" }, function(err, result){
console.log(result);
});
});
});

How to output mongodb collections in nodejs app to get them in response

I am using Cloude 9 environment for developing my nodejs app. In that I have written code to connect to mongodb database. I am successfully connecting to database and adding record to collection.
Now I want to send the collection info in return. But using res.send(collectionInfo); is not working.
Let me know how should I achieve this
Below is the code of my server.js file
var Db = require('mongodb').Db;
var http = require('http');
var path = require('path');
var async = require('async');
var socketio = require('socket.io');
var express = require('express');
var ejs = require('ejs');
var app = express();
var helpers = require('express-helpers')
var MongoClient = require('mongodb').MongoClient;
var Server = require('mongodb').Server;
var db;
helpers(app);
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended: true})); // for parsing application/x-www-form-urlencoded
var server = http.Server(app);
server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function () {
var addr = server.address();
console.log("Chat server listening at", addr.address + ":" + addr.port);
});
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/public/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
//app.use(express.static(__dirname + '/client'));
app.use(express.static(path.join(__dirname, '/client')));
// MongoDB Connection
app.use(function(req, res, next) {
next();
})
app.get('/monogdb', function (req, res) {
res.render('monogdb.ejs');
});
app.post('/ajax-mongo-connect', function (req, res) {
var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
if(err){
console.log(err);
}else{
var db = mongoClient.db("mydb");
db.createCollection("students", { name : req.body.nm, description : req.body.desc, location : req.body.loc } );
console.log('database connected',db);
var collectionInfo = db.collection("students");
mongoClient.close();
//res.setHeader('Content-Type', 'application/json');
res.send(collectionInfo);
}
})
})
As per #Roman Sachenko answer, I have tried to use
res.send(collectionInfo.toJSON()); but it is giving below error
/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:299
throw err;
^
TypeError: Object #<Collection> has no method 'toJSON'
at /home/ubuntu/workspace/server.js:66:41
at MongoClient.open
(/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/mongo_client.js:103:5)
at Db.open (/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:296:11)
at process._tickCallback (node.js:442:13)
and using res.send({data: collectionInfo}); gives error
home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:299
throw err;
^
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at ServerResponse.res.json (/home/ubuntu/workspace/node_modules/express/lib/response.js:185:19)
at ServerResponse.res.send (/home/ubuntu/workspace/node_modules/express/lib/response.js:117:21)
at /home/ubuntu/workspace/server.js:67:21
at MongoClient.open (/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/mongo_client.js:103:5)
at Db.open (/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:296:11)
at process._tickCallback (node.js:442:13)
Try to return this: res.status(200).json({'myCollection' : collectionInfo});.
You can find more details about express response here
Update:
After you explain the details, take a look at the code below:
app.post('/ajax-mongo-connect', function (req, res) {
var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
if(err){
console.log(err);
res.status(500).json({message : 'OMG, an error occurred'});
}else{
var db = mongoClient.db("mydb");
db.createCollection("students", { name : req.body.nm, description : req.body.desc, location : req.body.loc } );
console.log('database connected',db);
var collectionInfo = db.collection("students");
// Here we will find all students
collectionInfo.find({}).toArray(function(err, students) {
// so now, we can return all students to the screen.
res.status(200).json({'myCollection' : students});
}
}
})
})
Cheers!
Mongoose ODM
First of all I would like to recommend you using Mongoose ODM:
https://github.com/Automattic/mongoose
So you will make you work with database much easier.
Basically it returns (Mongoose) normal object as results, but in case of issues you may try to use toObject() or toJSON() or as it mentioned create own object like {data: mongoCollection}
Examples:
res.send(collectionInfo.toObject());
res.send(collectionInfo.toJSON());
res.send({data: collectionInfo});
Please refer to the link in case of questions:
http://mongoosejs.com/docs/guide.html#toJSON
Native Driver
As for native driver, it also should return normally-constructed object, but according to issues I faced with in the past, JSON.stringify always helps if you set headers manually.
You may also check the contents of your entity. So you can just output it by console.log(collectionInfo);
Then just make sure that there is correct object inside.
And according to results you can take actions like:
res.send(JSON.stringify(collectionInfo)) //set headers manually
res.json(JSON.stringify(collectionInfo)) //you don't need to set headers
At least you will know what exactly is inside of collectionInfo. I think it will be enough to investigate the issue.
You can view circular JSON objects by doing this in node.js:
const util = require('util') // Native node module
util.inspect(circularObj)
You can call it from anywhere in the code, so it's very versatile.

ReferenceError for Heroku MongoLab Connect

I am very close to an express app working in a sandbox environment on Heroku with a MongoDB addon..
I am still seeing a ReferenceError in the log, which seems to be the reason for the app crashing.
The first error was regarding this configuration:
//MongoDB
var mongodb = require('mongodb');
var db;
var MONGODB_URI = process.env.MONGOLAB_URI;
var PORT = process.env.PORT;
mongodb.MongoClient.connect(MONGODB_URI, function(err, database) {
if(err) throw err;
db = database;
app.listen(PORT);
console.log('Listening on port ' + PORT);
});
var testColl = db.collection('test');
That led to the log reading a TypeError, probably because db was defined locally..
app[web.1]: var testColl = db.collection('test');
app[web.1]: TypeError: Cannot call method 'collection' of undefined
And the recent error was a ReferenceError:
app[web.1]: var db = database;
app[web.1]: ReferenceError: database is not defined
Probably because database is defined globally, but not referenced within the context of the connection..
//MongoDB
var MongoClient = require('mongodb').MongoClient,
var Server = require('mongodb').Server;
var mongoUri = process.env.MONGOLAB_URI;
var port = process.env.PORT;
var db = database;
var mongoclient = new MongoClient(new Server(mongoUri,
{ 'native_parser' : true }));
var testColl = db.collection('test');
mongoclient.open(function (err, mongoclient) {
if (err) throw err
app.listen(port);
console.log("Express server started on port " + port);
});
How can I reformat the code to launch this app on Heroku?
Your first example looks close to working, but there's one thing wrong. mongodb.connect is an asynchronous call, which means it returns right away. That's why it has the callback parameter. Because the code runs so fast, it doesn't have time to actually connect to the database before you try to use the db object, which is what causes your crash in the first set of code.
If you move your database call inside the callback, it should work.
Edit: This is in reply to your comment, but I can't include much code in another comment, so you get an edit.
It really depends on your use case, but I realize that's not very helpful. So here's one way you could do it:
module.exports = function() {
return db;
};
By doing so, you would be able to require it from another file, and use it as such:
var http = require('http');
var db = require('./db.js');
http.createServer(function(req, res) {
db().collection('test', function(err, collection) {
console.log(err, collection);
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('We got it! Unless there is an error...\n');
});
}).listen(8080);
There's definitely ways to improve upon that, but it should get you started.

GET http://localhost:3000/socket.io/socket.io.js 404 (Not Found)

I'm trying to stream data to the browser. I'm struggling, however, to connect it to the browser. Here's my html:
<ul class="tweets"></ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
jQuery(function ($) {
var tweetList = $('ul.tweets');
socket.on('tweet', function (data) {
tweetList .prepend('<li>' + data.user + ': ' + data.text + '</li>');
});
});
</script>
And here's the relevant parts of my app.js:
var express = require('express')
, twitter = require('ntwitter')
, http = require('http')
, path = require('path');
var app = express();
var io = require('socket.io').listen(app);
app.get('/', function (req, res) { res.sendfile(__dirname + '/index.html'); });
app.listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
io.sockets.volatile.emit('tweets', {
user: data.user.screen_name,
text: data.text,
geo : geo,
latitude: latitude,
longitude: longitude
});
I installed socket.io 0.9.16 via my packages.json file:
"dependencies": {
"express": "3.2.6",
"jade": "*",
"ntwitter":"0.2.10",
"socket.io":"0.9.x"
}
Can anyone help me out here? Why can't it find the file?
Digging a bit deeper. To test the socket, I put this in the app.js:
var socket = io.listen(app);
And I get the error:
TypeError: Object #<Manager> has no method 'listen'
at Object.<anonymous> (/home/andy/dev/node/mytwittermap/app.js:49:17)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3
Your setup needs to look something like this:
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
...
server.listen(app.get('port')); // not 'app.listen'!
Can you try this:
var http = require('http');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
I guess, you will have to instantiate the socket.io server.
You need to instantiate the socket.io connection and
You need to use server.listen() and not app.listen()
Try something like this:
// at the top of app.js
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
// your code
// at the bottom of app.js
server.listen('3000', () => {
console.log('Server listening on Port 3000');
})

Resources