Node Express Mongodb connection syntax and error handling - node.js

I was having an issue in my app that was simply from an oversight on the database name that I provided to my mongodb connection. While looking around I ran across the examples here:
https://wesleytsai.io/2015/08/02/mongodb-connection-pooling-in-nodejs/
So my question is why don't I get any kind of error thrown if I am providing a database that does not exist to the mongodb connection? I just need help interpreting/understanding the syntax below. On this line:
MongoClient.connect(mongoUrl, function(err, database) {
if( err ) throw err;
.
.
.
shouldn't an error be thrown since mongo can't connect if the database doesn't exist?
What I'm trying to do is setup some kind of error handling that can flag the fact the the database doesn't exist and likewise with the collection if that too does not exist ('expenses' should be 'test').
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var mongoUrl = 'mongodb://127.0.0.1:27017/expenses';
var db;
exports.connect = function(callback) {
MongoClient.connect(mongoUrl, function(err, database) {
if( err ) throw err;
db = database;
callback();
})
}

In mongodb, if you are connected to the datbase and then you provide a schema to a collection that you defined, then irrespective of the fact that whether that collection is there or not, mongodb creates a collection for you.
For example if you have the following code,
module.exports = mongoose.model('User', schema);
a collection named users is created in the database. So even if you dont have a collection, mongodb will create one for you.
If you want to check whether a database exists then follow like below:
var mongoose = require('mongoose')
, Admin = mongoose.mongo.Admin;
/// create a connection to ypur database
var connection = mongoose.createConnection(
'mongodb://user:password#localhost:port/your_database');
connection.on('open', function() {
// connection successful
new Admin(connection.db).listDatabases(function(err, result) {
console.log('listDatabases successful');
// the database lists are stored in result.databases
var allDatabases = result.databases;
// allDatabases contains the record of all the databases
// crosscheck this list with the database you want
});
});

Related

Unable to extract collection names from mongodb

I have a mongodb (simple_demo) with an employee collection inside.
I am trying to connect to node JS and list the collections inside the simple_demo db.
I tried doing this but nothing came back. it just shows [].
Am wondering if I did anything wrong?
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/simple_demo');
var db = mongoose.connection;
db.on('open', function () {
console.log("connection ok");
db.db.listCollections().toArray(function (err, names) {
console.log(names); // [{ name: 'dbname.myCollection' }]
module.exports.Collection = names;
});
});
Good day
Your code works. Check your database.

How can I get all mongoDB collection names using Node.js code?

I want to store all collection names of MongoDB in a variable/array. How can I write nodeJS code to do that?
create a connection by providing connection url.
create a client to db using database name client.db(dbName);
call listCollections method to get detail info of each collection.
finally filter and push the required information and close the connection.
const mongo = require('mongodb').MongoClient;
mongo.connect(connectionUrl, function(err, client) {
let allCollections = [];
//create client by providing database name
const db = client.db(dbName);
db.listCollections().toArray(function(err, collections) {
if(err) console.log(err);
//iterate to each collection detail and push just name in array
collections.forEach(eachCollectionDetails => {
allCollections.push(eachCollectionDetails.name);
});
//close client
client.close();
});
});
await db.listCollections().toArray().map(c => c.name);
This returns a string array containing the name of every collection.

Mongoose findById is returning null

So I have this schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TreeSchema = new Schema({
}, { collection: 'treeLocations' });
var TreeDetailsSchema = new Schema({
}, { collection: 'treeInfo' });
module.exports = mongoose.model('Tree', TreeSchema);
module.exports = mongoose.model('TreeDetail', TreeDetailsSchema, "treeInfo");
And I am calling by ID like this:
var TreeDetails = require('./app/models/tree').model('TreeDetail');
router.route('/api/trees/:tree_id')
.get(function(req, res) {
TreeDetails.findById(req.params.tree_id, function(err, treedetail) {
if (err)
res.send(err);
res.json(treedetail);
});
});
For some reason - http://localhost:3000/api/trees/5498517ab68ca1ede0612d0a which is a real tree, is returning null
Something that might help you help me:
I was following this tutorial: https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
The only thing I can think of that changed is that I have a collection name. Might that be it?
The step that I don't see is how you actually connect to MongoDB and after that, how you get the Model from the connection.
// connect to MongoDB
var db = mongoose.createConnection('mongodb://user:pass#host:port/database');
// now obtain the model through db, which is the MongoDB connection
TreeDetails = db.model('TreeDetails');
This last step is how you associate your model with the connected mongo database.
More info on Mongoose.model
There are several ways to establish a connection to MongoDB with mongoose, the tutorial uses:
mongoose.connect('mongodb://node:node#novus.modulusmongo.net:27017/Iganiq8o');
(Personally I prefer the more explicit mongoose.createConnection as shown in the example)
(I used mongoose 4.3.1 for this example)
My steps to reproduce, in order to provide a working example (without creating a webservice for it):
var mongoose = require('mongoose'),
TreeDetails, db;
// create the model schema
mongoose.model('TreeDetails', mongoose.Schema({
// .. your field definitions
}, {collection: 'treeInfo'}));
db = mongoose.createConnection('mongodb://user:pass#host/example');
TreeDetails = db.model('TreeDetails');
TreeDetails.findById('5671ac9217fb1730bb69e8bd', function(error, document) {
if (error) {
throw new Error(error);
}
console.log(document);
});
Instead of:
var TreeDetails = require('./app/models/tree').model('TreeDetail');
try:
var mongoose = require('mongoose'),
TreeDetails = mongoose.model('TreeDetail');
Defining the collection name shouldn't give you any issues. It's just what the collection will be called in the database / when using the mongo shell.
And just to be sure, try logging req.params.tree_id before calling findById to make sure it's coming through as you suspect.

Telling Mongoose which database to use - in a node.js Express application

I have an Node.js Express web app running.
I have two database connections, the system_db is created with "Mongoose.connect", the user_db is created with "Mongoose.createConnection". This seems to make them separate and have different connection pools. Although this could be the crux of the problem.
I have code dealing with with a Mongoose model
in the model file I have:
var authSchema = mongoose.Schema({
teamName: String,
league: String,
players: []
});
var Team = module.exports = mongoose.model('teams',authSchema);
in my main file I have two connections:
one is a system database
connection_uri = "mongodb://localhost:27017/";
system_db = mongoose.connect(connection_uri.concat("sparks"), {
native_parser : true
}, function(err){
if (err) throw err;
});
the other is a user database
user_db = mongoose.createConnection(connection_uri.concat(user_id));
then I have this piece of code in my main file which finds a Team object based off id:
app.param('team_id', function(req, res, next, team_id) {
Team.findOne(team_id, function(err, team) {
if (err) {
return next(err);
}
if (!team) {
throw new Error("no team matched");
}
req.team = team;
next();
});
});
the problem is that the app.param function above is not finding any matches for teams, even though they exist in a collection in the user_db database. this means, that I am thinking my model is pointing to the wrong database somehow? Somehow it must be pointing to this system_db instead of the user_db. Could this be right? How would I fix that?
The below method opens a connection to the system_db and is binded to the mongoose object,.i.e the current mongoose object is modified. The return type is not a Connection.
system_db = mongoose.connect(connection_uri.concat("sparks")...
Now when you again do:
user_db = mongoose.createConnection(connection_uri.concat(user_id));
This creates a new Connection to the user database and returns a connection, but does not modify the mongoose instance. The mongoose instance is still binded to the system_db database connection.
Since Team model is obtained from the same mongoose instance,
var Team = mongoose.model('teams',authSchema);
whatever operation is done on this model effectively occurs in the connection that the mongoose instance holds, and that is of the system_db database.
So you need to obtain the model from the user_db connection :
var user_db = mongoose.createConnection(..);
// retrieve the Team model
var Team= user_db.model('teams'); // not from mongoose instance.
use createConnection wherever you want to obtain a connection.

Mongoose migrate

Anyone got a migrate module that they use to migrate mongodb data with the mongoose plugin?
I am currently using the 'migrate' module and it works great except for the fact that I need to create/destroy my connection in each up/down.
I.E.
// Setup mongoose
var mongoose = require('mongoose')
, Role = require('../models/role')
, User = require('../models/user');
exports.up = function(next) {
// get a brand new connection for this patch.
mongoose.connect('mongodb://localhost/sagedb');
var adminUser = {
username: 'admin',
password: 'admin'
};
User.createUser(adminUser, function(err, user) {
if (err) {
mongoose.disconnect(); // Make sure to close connection
return next(err);
}
mongoose.disconnect(next); // Make sure to close connection
});
};
exports.down = function(next) {
mongoose.connect('mongodb://localhost/sagedb'); // new connection for down
User.getUserByUsername('admin', function(err, user) {
if (err) {
mongoose.disconnect(function() { // make sure to close connection
return next(err);
});
}
if (!user) {
mongoose.disconnect(); // make sure to close connection
return next();
}
User.deleteUser(user, function(err, user) {
console.log('deleted user');
mongoose.disconnect(next); // make sure to close connection
});
});
};
Probably a much better way to do this. Wondering if the only option is to create my own module that starts the connection once and closes it when all patches are complete.
I have seen mongoose-migrate which tracks migration in database collection. Not really specific to mongoose IMHO, I would rather still use the .migrate file but only have to open the connection once.
The reason of the issue is that you have connection "connected" each time, on every ,migration
That is why you have to disconnect.
The same situation if you replace connect with mongoose.createConnection. you will need to close it.
How to solve?
move
var mongoose = require('mongoose')
, Role = require('../models/role')
, User = require('../models/user');
into module like db
var mongoose = require('mongoose')
, Role = require('../models/role')
, User = require('../models/user');
module.exports = mongoose
and just require it
var mongoose = require('./db')
So you will have:
Single connection
All models loaded in one place
Clean code in
migrations
You can also try my migrate-mongoose migration framework which provides the mongoose connection right out of the box.
in your up or down function you can just access your models like this
this('user').findOne({ name: 'Sergey' });
It also persists your migrations to the database instead of the file system.
You also have east migration framework that is very powerful and it also has mongoDB adaptors:
https://github.com/okv/east
Then you will crate migration with command:
east create my_migration_name
And then your migration scripts will look like this:
exports.migrate = function(client, done) {
var db = client.db;
db.........
done();
};
exports.rollback = function(client, done) {
var db = client.db;
db.........
done();
};

Resources