How to check if db exists during mongodb connection using mongoose.connect? - node.js

I've tried to use mongoose.connect to check if a db exists,
mongoose.connect("mongodb://localhost:27017/notexistdb",function(err){
if(err) console.log(err);
});
The callback doesn't contain error message, so how can I determine whether the database exists or not.

You can easily find out by getting database list.
var mongoose = require('mongoose')
, Admin = mongoose.mongo.Admin;
/// create a connection to the DB
var connection = mongoose.createConnection(
'mongodb://user:pass#localhost:port/database');
connection.on('open', function() {
// connection established
new Admin(connection.db).listDatabases(function(err, result) {
console.log('listDatabases succeeded');
// database list stored in result.databases
var allDatabases = result.databases;
});
});

You could try using open and error events to see if you can connect to the database. If you can connect to it, then it exists. If you can't, then it doesn't.
var mongoose = require('mongoose');
mongoose.connection.on('open', function (ref) {
console.log('Connected to Mongo server...');
});
mongoose.connection.on('error', function (err) {
console.log('Could not connect to Mongo server...');
console.log(err);
});
mongoose.connect('mongodb://localhost:27017/notexistdb',function(err){
if(err) console.log(err);
});

If you want to get your answer returned, you need to use the desync library.
Install desync using npm i desync
You can also use the following function in a different file by exporting it.
const mongoose = require("mongoose");
var Admin = mongoose.mongo.Admin;
const deasync = require("deasync");
function checkDatabase (dbName) {
var check; // we will return this value
var uri = "mongodb://localhost:27017/";
// connect with mongoDB
mongoose.connect(uri, {useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true})
.then(() => {
new Admin(mongoose.connection.db).listDatabases((err, result) => {
var allDatabases = result.databases;
check = allDatabases.some((database) => database.name === dbName);
});
})
.catch((err) => {
console.log("some error occured");
});
// wait while mongoose executes the result
while (check == null) {
deasync.runLoopOnce();
}
return check; // either true or false
};
We need to use desync because much of the node's functionalities are asynchronous. To know more: Click Here - Callback Functions

Related

Node.js/Express: How Do I Share or Export Mongo Database Connection To Other Modules?

I am trying to share the Mongo connection with other modules in my Node.js project. I keep getting either undefined or is not a function when attempting to use the exported client. I also had a question around detecting if the connection is in fact open before performing operations on the database.
It seems like using the app.locals would be the proper way to share the connection but I could not get that working either. Below is what I have at the moment. I've tried this many ways. Most of what I can find online seems to export the Mongo Node driver's method, not the connection itself. The idea is to connect once and never disconnect until the app shuts down.
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
async function connect () {
app.locals.dbConnected = false;
try {
await client.connect();
app.locals.dbConnected = true;
module.exports = client;
} catch (e) {
console.error(e);
}
};
then in another module do something like:
await client.db('syslogs').collection('production').insertOne(doc);
Is it possible to share the connection?
Could do something like below:
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
let __inst = null;
export default new Promise((resolve, reject) => {
if (__inst !== null) resolve(__inst);
// the open event is the key here
// like this we can handle error, close etc thru events as well
client.open((err, mongoInst) => {
if (err) reject(err);
__inst = mongoInst;
resolve(__inst);
});
});
Then in other module you can use the export client like you want.
Thanks.
I just got it working using app.locals.
index.js
const { MongoClient } = require("mongodb");
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
(async () => {
app.locals.dbConnected = false;
try {
await client.connect();
console.log("Connected to DB");
app.locals.client = client;
app.listen(PORT, HOST, () => {
console.log(`Running on http://${HOST}:${PORT}`);
});
} catch (e) {
console.error(e);
}
})();
Then in my module:
async function index (req, res) {
try {
let db = req.app.locals.client.db("admin");
await db.command({ ping: 1 });
console.log("pinged admin database");
}catch(err) {
console.log(err);
}
}

Mongo database objects says undefined if do not check for err

I am currently trying to learn how to use MongoDB. I tried two similar but slightly different pieces of code and received completely different results. I am trying to understand why this happened.
CODE 1
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useNewUrlParser: true }, function(err, client) {
if (err) throw err
var db = client.db('EmployeeDB')
var cursor = db.collection('Employee').find()
cursor.forEach(function(err, doc) {
console.log(doc);
console.log("Hello")
});
client.close()
});
CODE 2
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useNewUrlParser: true }, function(err, client) {
if (err) throw err
var db = client.db('EmployeeDB')
var cursor = db.collection('Employee').find()
cursor.forEach(function(err, doc) {
if (err) {
console.log(err)
} else {
console.log(doc);
}
});
client.close()
});
Code 1 returned "undefined \n undefined \n undefined". However, Code 2 returned the actual objects and their information. I was wondering why only the second piece of code works correctly.
There is only one argument in the callback of cursor.forEach(), not two. Hence in both cases, "doc" is not defined, and only "err" is defined (which is the actual document).
Your code should thus be:
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useNewUrlParser: true }, function(err, client) {
if (err) throw err;
var db = client.db('EmployeeDB');
var cursor = db.collection('Employee').find();
cursor.forEach(function(doc) {
console.log(doc);
});
client.close();
});
From MongoDB official docs:
The signature includes a single argument that is passed the current document to process.
Source: https://docs.mongodb.com/manual/reference/method/cursor.forEach/

best way to execute query in mongodb(3.0 drivers) and nodejs

db.js
var mongodb = require('mongodb').MongoClient;
var settings = require("./settings.js");
var ObjectId = require('mongodb').ObjectID;
var db = {
selectData: function(collection, query, callback, project = false) {
mongodb.connect(settings.db_url, function(err, client) {
var database = client.db(settings.db_name);
if (err) throw err;
if (project !== false) {
console.log("Project is not false");
console.log( project);
database.collection(collection).find(query, project).toArray(function(err, result) {
client.close();
if (err) throw err;
callback(result);
});
} else {
database.collection(collection).find(query).toArray(function(err, result) {
client.close();
if (err) throw err;
callback(result);
});
}
});
}
}
module.exports = db;
server.js
here is a simple query with single database call takes few seconds not a big deal but still not good method as per experts.
var db = require("db.js");
db.selectData("testCollection",{},function(data){
console.log(data);
});
Now here is a multi query nested database calls which takes more time and really bad for performance and speed
var db = require("db.js");
db.selectData("testCollection", {}, function(data) {
db.selectData("testCollection", {}, function(data) {
db.selectData("testCollection", {}, function(data) {
db.selectData("testCollection", {}, function(data) {
db.selectData("testCollection", {}, function(data) {
console.log(data);
});
});
});
});
});
What i want is open connection once and use db object outside without connecting again and again for each request or nested querys for fast response
i also know that with mongodb nodejs 2.3 drivers its possible and i have tested it perfectly working but i am looking for solution how to do same with mongodb nodejs 3.0 drivers
in short i am looking for a method where i can connect once and execute querys faster for chat and real time applications and performance optimizations
thank you.
Here i found a great working code with nodejs 3.0 Mongodb drivers
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
var express = require('express');
var app = express();
const url = 'mongodb://Your connection string';
const dbName = 'your database name';
MongoClient.connect(url, function(err, client) {
const db = client.db(dbName);
app.get("/", function(req, res) {
db.collection("somedata").find({}).toArray(function(err, result) {
if (err) throw err;
res.send(JSON.stringify(result));
});
});
app.listen(3000);
});
Instead of connecting again and again for each request connect at once and use it for best way if database connection is lost you can connect again but here you have to use some logic to make live that connection again and app routes too
this works for me i hope it will work for developers looking for answers of this question

ES6 : How to export this variable of node.js?

There is a piece of code that querying data from mongodb with node.js:
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
//a query that returns all the documents
var findDocuments = function(db, callback) {
// Get the documents collection
var collection = db.collection('documents');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
callback(docs);
});
}
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");
var result = findDocuments(db, function() {
db.close();
});
});
//export the query result,but it doesn't work because it is a local variable in `MongoClient.connect()`
export {result}
Question:
I want to export the variable result, but it doesn't work because it is a local variable in MongoClient.connect().What should I do?
Define it outside the function like
var result
You need to define it globally in the document.
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
var result; //define it out here to be able to use it on anywhere
//a query that returns all the documents
var findDocuments = function(db, callback) {
// Get the documents collection
var collection = db.collection('documents');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
callback(docs);
});
}
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");
result = findDocuments(db, function() { //give it its value
db.close();
});
});
//export the query result,but it doesn't work because it is a local variable in `MongoClient.connect()`
export {result}
If you are using ES6, I would recommend to use the keywords let/const instead of var.
Now about your issue why would you export result that way?
You should create a function connect() and export it. Then in your controller, call this function and handle whatever the outcome is.
Your connect here is totally asynchronous and uncontrolled, which is very bad behavior.
Exemple of what to do :
file mongodb.es6
export default class Mongodb {
connect() {
...
}
...
}
file main.es6
const mongodbObject = new Mongodb();
mongodbObject.connect()
.then(() => {
// I am connected so I can do whatever I want
})
.catch((err) => {
// I have an error and do something about it
});
Don't do it like this!
This will ONLY query the data when the file is being executed. I don't see any reason to do it this way.
Instead expose a function from this file, which will connect to the DB, query it and return the result object, everytime you call it.
export {
getResult: function(query, callback) {
// Connection URL
var url = 'mongodb://localhost:27017/myproject';
// Use connect method to connect to the server
MongoClient.connect(url, function(err, db) {
if (err) return callback(err);
console.log("Connected correctly to server");
result = findDocuments(db, function() {
db.close();
});
callback(null, result);
});
}
}

Check if mongoDB is connected

I have mongoDB in my app.
I want to check if mongoDB is connected, before I listen to the app.
Is it the best way for doing it?
This is my server.js file:
var express = require('express');
var mongoDb = require('./mongoDb');
var app = express();
init();
function init() {
if (mongoDb.isConnected()) {
app.listen(8080, '127.0.0.1');
}
else {
console.log('error');
}
}
isConnected runs getDbObject.
getDbObject connects to mongoDB and returns an object:
connected (true/false), db (dbObject or error).
Then, isConnected resolve/reject by connected property.
This is mongoDb.js file:
//lets require/import the mongodb native drivers.
var mongodb = require('mongodb');
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/myDb';
var connectingDb; // promise
//We need to work with "MongoClient" interface in order to connect to a mongodb server.
var MongoClient = mongodb.MongoClient;
init();
module.exports = {
isConnected: isConnected
}
// Use connect method to connect to the Server
function init() {
connectingDb = new Promise(
function (resolve, reject) {
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
reject(err);
}
else {
console.log('Connection established to', url);
//Close connection
//db.close();
resolve(db);
}
});
}
);
}
function getDbObject() {
return connectingDb().then(myDb => {
return {
connected: true,
db: myDb
}
}
)
.catch(err => {
return {
connected: false,
db: err
}
}
)
}
function isConnected() {
return new Promise(
function(resolve, reject) {
var obj = getDbObject();
if (obj.connected == true) {
console.log('success');
resolve(true);
}
else {
console.log('error');
reject(false);
}
}
)
}
Any help appreciated!
there are multiple ways depends on how your DB is configured. for a standalone (single) instance. You can use something like this
Db.connect(configuration.url(), function(err, db) {
assert.equal(null, err);
if you have a shared environment with config servers and multiple shards you can use
db.serverConfig.isConnected()
Let client be the object returned from MongoClient.connect:
let MongoClient = require('mongodb').MongoClient
let client = await MongoClient.connect(url ...
...
This is how i check my connection status:
function isConnected() {
return !!client && !!client.topology && client.topology.isConnected()
}
This works for version 3.1.1 of the driver.
Found it here.
From version 3.1 MongoClient class has isConnected method. See on https://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html#isConnected
Example:
const mongoClient = new MongoClient(MONGO_URL);
async function init() {
console.log(mongoClient.isConnected()); // false
await mongoClient.connect();
console.log(mongoClient.isConnected()); // true
}
init();
There has been some changes since version 3, isConnected is no longer available in version 4. The correct way of dealing with an ambiguous connection is to just call MongoClient.connect() again. If you're already connected nothing will happen, it is a NOOP or no-operation, and if there is not already a connection you'll be connected (as expected). That said, if you really want to know if you have a connection try something like this:
const isConnected = async (db) => {
if (!db) {
return false;
}
let res;
try {
res = await db.admin().ping();
} catch (err) {
return false;
}
return Object.prototype.hasOwnProperty.call(res, 'ok') && res.ok === 1;
};

Resources