How to connect to MongoDB with Node.js? And then pass the result to a client side JavaScript and display in HTML.
var http = require('http');
var URL = require('url');
var Db = require('mongodb').Db;
var Server = require('mongodb').Server;
var client = new Db('people', new Server("127.0.0.1", 27017, {}), { safe: false });
client.open(function (err, client) {
client.collection('people', listAllData);
});
var listAllData = function (err, collection) {
collection.find().toArray(function (err, results) {
console.log(results);
});
}
You should use Mongoose - elegant mongodb object modeling for node.js. http://mongoosejs.com
The quickstart guide is really cool, you should read it.
According to the documentation, here is a small example of how to use Mongoose:
var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'test');
var schema = mongoose.Schema({ name: 'string' });
var Cat = db.model('Cat', schema);
var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
if (err) // ...
console.log('meow');
});
I prefer MongoJS to Mongoose because it uses the same syntax used by the MongoDB Client syntax
https://github.com/gett/mongojs
// simple usage for a local db
var db = mongojs('mydb', ['mycollection']);
// the db is on a remote server (the port default to mongo)
var db = mongojs('example.com/mydb', ['mycollection']);
// we can also provide some credentials
var db = mongojs('username:password#example.com/mydb', ['mycollection']);
// connect now, and worry about collections later
var db = mongojs('mydb');
var mycollection = db.collection('mycollection');
Then you can use the same syntax as the Mongo Client
db.mycollection.find({}, function(err, docs) { ... });
db.mycollection.find({}).limit(2).skip(1, function(err, docs) { ... });
Related
I am trying to write a simple code to fetch some data from MongoDB in express.
Below is my code:
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017/mcart'
MongoClient.connect(url)
.then(function (db) {
console.log(db)
})
.catch(function (err) {})
This gives me a JSON. But, when I try to access data from it, I get an error "db.collection" is not a function
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017/mcart'
MongoClient.connect(url)
.then(function (db) {
var cursor=db.collection("product_catalog").find();
cursor.each(function(err, doc) {
console.log(doc);
});
})
.catch(function (err) {console.log(err)})
Where am I going wrong?
Use hasNext(). It will move to the next doc in the cursor until it reaches to the end. Also get the database name before querying the collection
var DbName = db.db("databaseNameHere");
var cursor = DbName.collection("product_catalog").find();
while (cursor.hasNext()) {
console.log(tojson(cursor.next()));
}
Change your code to:
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017/mcart'
MongoClient.connect(url)
.then(function (db) {
console.log("Before")
var DbName = db.db("databaseNameHere");
var cursor=DbName.collection("product_catalog").find();
while (cursor.hasNext()) {
console.log(tojson(cursor.next()));
}
console.log("after")
})
.catch(function (err) {})
As you are using ^3.0.x this is the way to connect and execute queries.
Using MongoDB nodejs driver with version ^3.0.x gives you client object as callback function argument.
MongoClient.connect('mongodb://localhost:27017', (err, client) => {
if(err)
throw err
// Client returned
var db = client.db('mcart');
db.collection("product_catalog").find();
...
});
The way you're doing is the old way, used in 2.x version where it gives you db object as an argument to the callback function.
Read more about the change logs here
I tried the below code and this is working fine. This code is basically a combination of the other two answers. Just posting it for others in future.
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017'
var databaseName="mcart";
MongoClient.connect(url)
.then(function (mongoClientInstance) {
var database = mongoClientInstance.db(databaseName);
var x=database.collection("product_catalog").find().toArray();
return x;
})
.then(x=>console.log(x))
.catch(err=>console.log(err))
Hey guys so I'm pretty new to creating modules, I'm having a bit of trouble accessing my mongodb connection pool from my main application.
Here's the module:
// mongo-pool.js
// -------------
var assert = require('assert');
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'connection_url';
var mongoPool = {
start: function() {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Successfully connected to mongo");
// Make the db object accessible here?
});
}
}
module.exports = mongoPool;
When I require mongo-pool.js and call mongoPool.start() It says it successfully connected to mongo, although the db object is not accessible to make queries. Here is the main js file:
var mongoPool = require('./mongo-pool.js');
var pool = mongoPool.start();
var collection = pool.db.collection('accounts');
collection.update(
{ _id: 'DiyNaiis' },
{ $push: { children: 'JULIAN' } }
)
The variable pool is undefined. I can't seem to figure out why, I've tried return db in the module, didn't seem to work.
Any help is appreciated, thank you!
A buddy of mine helped me figure out what the problem was, here's the solution incase anyone runs into it.
I updated my mongo-pool.js module and assigned the db property to itself:
var assert = require('assert');
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'my_database_url';
var mongoPool = {
start: function() {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
var self = this;
self.db = db;
// THESE ASSIGNMENTS
console.log("Successfully connected to mongo");
// Make the db object accessible here?
});
}
}
module.exports = mongoPool;
Then in my main.js file:
var mongoPool = require('./mongo-pool.js');
// Include My mongo global module
new mongoPool.start();
// Initialize the new MongoDB object globally
setTimeout(function() {
console.log(db);
}, 3000);
// Set a 3 second timeout before testing the db object...
// It will return undefined if it's called before the mongo connection is made
Now the db object is globally available from a module.
In the documentation of Algolia, for the node.js part they specified to use MySQL for indexing but not MongoDB, I have another question regarding this issue but it is more a general question , check here
Some folks ask me to use mongo-connector but tried it and I got some unknown error, which got me to square one
My real question is, how do i iterate a list of collections in mongodb to algolia?
This is the Algolia's version of MySQL in Node.js
var _ = require('lodash');
var async = require('async');
var mysql = require('mysql');
var algoliasearch = require('algoliasearch');
var client = algoliasearch("RQGLD4LOQI", "••••••••••••••••••••••••••••••••");
var index = client.initIndex('YourIndexName');
var connection = mysql.createConnection({
host: 'localhost',
user: 'mysql_user',
password: 'mysql_password',
database: 'YourDatabaseName'
});
connection.query('SELECT * FROM TABLE_TO_IMPORT', function(err, results, fields) {
if (err) {
throw err;
}
// let's use table IDS as Algolia objectIDs
results = results.map(function(result) {
result.objectID = result.id;
return result;
});
// split our results into chunks of 5,000 objects, to get a good indexing/insert performance
var chunkedResults = _.chunk(results, 5000);
// for each chunk of 5,000 objects, save to algolia, in parallel. Call end() when finished
// or if any save produces an error
// https://github.com/caolan/async#eacharr-iterator-callback
async.each(chunkedResults, index.saveObjects.bind(index), end);
});
function end(err) {
if (err) {
throw err;
}
console.log('MySQL<>Algolia import done')
};
To be specific I'm using mongoose as my ORM, so I have no experience in other libraries. Please help me on this, so that I could some searching interface already :(.
You can use the following code to iterate over the whole MongoDB mydb.myCollection collection + create batches that will be sent to the Algolia index:
var Db = require('mongodb').Db,
Server = require('mongodb').Server,
algoliasearch = require('algoliasearch');
// init Algolia index
var client = algoliasearch("*********", "••••••••••••••••••••••••••••••••");
var index = client.initIndex('YourIndexName');
// init connection to MongoDB
var db = new Db('mydb', new Server('localhost', 27017));
db.open(function(err, db) {
// get the collection
db.collection('myCollection', function(err, collection) {
// iterate over the whole collection using a cursor
var batch = [];
collection.find().forEach(function(doc) {
batch.push(doc);
if (batch.length > 10000) {
// send documents by batch of 10000 to Algolia
index.addObjects(batch);
batch = [];
}
});
// last batch
if (batch.length > 0) {
index.addObjects(batch);
}
});
});
how do i share the db object returned from when i call db.open or db.connect across the entire app?
i have a dbconnect.js module as follows :
var mongodb = require('mongodb');
var global_db = '';
// Define options. Note poolSize.
var serverOptions = {
'auto_reconnect': true,
'poolSize': 5
};
// Now create the server, passing our options.
var serv = new mongodb.Server('localhost', 27017, serverOptions);
// At this point, there is no connection made to the server.
// Create a handle to the Mongo database called 'myDB'.
var dbManager = new mongodb.Db('myDB', serv);
// NOW we initialize ALL 5 connections:
dbManager.open(function (error, db) {
// Do something with the connection.
global_db = db;
// Make sure to call db.close() when ALL connections need
// to be shut down.
db.close();
});
function getConnection()
{
return global_db;
}
exports.getConnection = getConnection;
and i am using this dbconnect.js in my app.js as:
var http = require('http');
var db = require('./dbconnect').getConnection();
var collection = db.collection('testcollection');
console.log(db);
console.log(collection);
var server = http.createServer();
server.on('request',route);
server.listen(8000,'127.0.0.1');
console.log('Server running at http://127.0.0.1:8000');
function route(request,response)
{
var url = request.url;
var doc = {};
doc[url] = 'ok';
collection.insert(doc,{w:1},function(err,result)
{
if(err) console.log(err);
else console.log(result);
});
}
in the console, the db and collection variable show empty values, i also tried removing the db.close() call in dbconnect.js but to no use, however the insertion works when i place it inside dbconnect.js file in the dbManager.open function, how do i do this?or any similar alternatives?
You can't do that, because dbManager.open( is async method, but you trying to get data from module synchronously.
Try this:
In dbconnect.js
var on_db_ready = null;
module.exports = {
db_ready:function(db_ready_callback){
on_db_ready = db_ready_callback;
//here we call callback if already have db
if (global_db) on_db_ready(global_db);
},
getConnection:getConnection
};
dbManager.open(function (error, db) {
if (on_db_ready) on_db_ready(db);
global_db= db;
})
in app.js:
var db = require('./dbconnect').db_ready(function(db){
//Here i have my database
//or can use getConnection method
});
this is not very beautiful way, but, I hope, explain your mistake
I am trying to run a simple mongoose/node example which I found here on stackoverflow:
var mongoose = require('mongoose'),
db = mongoose.connect('mongodb://localhost/db'),
Schema = mongoose.Schema;
var sentinel = setTimeout(function(){
throw "failed to connect to MongoDB after one minute!";
}, 60*1000); // 60 seconds
mongoose.model('User', new Schema({
properties: {
name : { type: String, index: true }
}
}));
var User = db.model('User');
var u = new User();
u.name = 'Foo';
u.save();
User.find().all(function(arr) {
clearTimeout(sentinel); // cancel the timeout sentinel
console.log('Users found');
console.log(arr);
console.log('length='+arr.length);
});
process.stdin.resume();
If I get the code right there should be an output in the terminal at the end of the script, where the message "Users found" and all users from the collection should be printed. But I just get the timeout message. Why that?
I am running my server on an Amazon EC2 micro instance. Node, Mongodb and mongoose are installed and a Mongodb server is running (I can interact with it from the terminal via "mongo"). I have also created the directory /data/db.
I don't know about mongoose but u.save() might be asynchronous because it writes to the DB. Try
u.save(function (err){
if(err) console.log(err);
User.find().all(function(arr) {
clearTimeout(sentinel); // cancel the timeout sentinel
console.log('Users found');
console.log(arr);
console.log('length='+arr.length);
});
});
Edit: This works fine
var mongoose = require('mongoose');
var connection = mongoose.connect('mongodb://localhost/my_database');
var Schema = mongoose.Schema
var User = new Schema({
author : String
, type : String
});
var MyUserModel = mongoose.model('User', User); //create and access the model User
var u = new MyUserModel();
u.author = 'authorname';
u.save(function(err){
if (err) console.log(err);
});
MyUserModel.find({}, function (err,docs) {
console.log(docs);
});
I handled this problem by adding one additional step in each router where I use DB.
It's a little bit messy but it works and 100% no leaks.
Something like this:
// file: 'routes/api/v0/users.js'
router
var User = require('../../../models/user').User,
rest = require('../../../controllers/api/v0/rest')(User),
checkDB = require('../../../middleware/checkDB');
module.exports = function (app) {
app.get('/api/v0/users', checkDB, rest.get);
app.get('/api/v0/users/:id', checkDB, rest.getById);
app.post('/api/v0/users', checkDB, rest.post);
app.delete('/api/v0/users', checkDB, rest.deleteById);
app.put('/api/v0/users', checkDB, rest.putById);
};
// file: 'middleware/checkDB.js'
var HttpError = require('../error').HttpError,
mongoose = require('../lib/mongoose');
// method which checks is DB ready for work or not
module.exports = function(req, res, next) {
if (mongoose.connection.readyState !== 1) {
return next(new HttpError(500, "DataBase disconnected"));
}
next();
};
PS If you know solution better, please let me know.