node app on shared hosting cpanel cannot connect to mongodb - node.js

I have been trying to connect to mongodb via my node app on a shared hosting cpanel but it only responds with error code 503 and logs "db.collection undefined" to the console, which means the connection was not successful.
This is the database connection in db.js:
const { MongoClient } = require('mongodb');
require('dotenv').config();
let dbConnection;
module.exports = {
connectToDb: (cb) => {
MongoClient.connect(`mongodb+srv://Achifa:${process.env.PASSWORD}#cluster0.exp9r.mongodb.net/?retryWrites=true&w=majority`)
.then((client) => {
dbConnection = client.db('newsDb')
return cb()
})
.catch(err => {
console.log(err)
return cb(err)
})
},
getDb: () => dbConnection
}
This is the app connection in app.js:
const {connectToDb, getDb} = require('./db');
let db;
var port = process.env.PORT || 50500;
connectToDb((err) => {
if(!err){
var server = app.listen(port, () => console.log("connected"));
db = getDb();
}
})

Related

MongoClient.connect is not responding

I am trying to connect my Node.js (Express) with my MongoDB atlas by following the official tutorial on their website.
Here is my conn.js code below:
const { MongoClient } = require("mongodb");
const Db = process.env.ATLAS_URI;
let _db;
module.exports = {
connectToServer: function (callback) {
MongoClient.connect(
Db,
{ useNewUrlParser: true, useUnifiedTopology: true },
(err, db) => {
console.log('THIS LOG IS NOT DISPLAYED')
if (db) {
_db = db.db("employees");
console.log("Successfully connected to MongoDB");
}
return callback(err);
}
);
},
getDb: function () {
return _db;
},
};
Here is server.js where I am calling connectToServer() function from conn.js
const express = require("express");
const app = express();
const cors = require("cors");
require("dotenv").config({ path: "./config.env" });
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
app.use(require("./routes/record"));
const dbo = require("./db/conn");
app.listen(port, () => {
// HERE IS WHERE I CALL THE FUNCTION
dbo.connectToServer(err => {
if (err) console.error(err);
});
console.log(`Server is running on port: ${port}`);
});
Note, that I am getting the "Server is running on port: 5000" message, but I am not getting the "Successfully connected to MongoDB" message and I am not getting any errors, too.
P.S. I made my MongoDB network access 0.0.0.0 so that any IP address can access it. And also if I provide the wrong username and password for my ATLAS_URI, I am getting an authentication error.
Connect returns promise you can use like below.
let _db;
const client = new MongoClient(Db, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
module.exports = {
connectToServer: async (callback) => {
await client.connect();
console.log("Connected successfully to server");
_db = client.db(dbName);
console.log("Successfully connected to MongoDB");
},
getDb: function () {
return _db;
},
};
Note: You can change the order If you want, First connect to DB then start the server. It's completely optional depending on the use case.
(async () => {
try {
await dbo.connectToServer();
app.listen(port, async () => {
// HERE IS WHERE I CALL THE FUNCTION
console.log(`Server is running on port: ${port}`);
});
} catch (error) {
console.log(error);
}
})();
Callback Support has been removed from v5 hence the console.log statements in callback function are not getting printed. To make it work you can use promises/async-await.
Due to same reason an error is thrown when authentication is wrong as connect function is running but failing in this case.
Change log for the same. => "Node.js driver v5 drops support for callbacks in favor of a Promise-only API."

how to use async and await to connect to mongoDB database?

I am new to JavaScript and currently learning mongoDB with node.
The code Bellow is in callback functions but i want to connect to mongoDB database using async and await with try and catch .
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/selfdb");
mongoose.connection
.once("open", () => {
console.log("connection has been made!");
})
.on("error", (error) => {
console.log("connection error:", error);
});
I tried doing this way:
const mongoose = require("mongoose");
async function main() {
const uri = "mongodb://localhost/selfdb";
const client = new mongoose(uri);
try {
await client.connect();
console.log("connection has been made!");
} catch (e) {
client.error(e);
} finally {
await client.close();
}
}
main().catch(console.error);
but i got following error:
TypeError: mongoose is not a constructor
how could i do it the right way?
am i doing any silly mistake?
I believe the better way to connect is like this
const mongoose = require('mongoose')
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI)
console.log(`MongoDB Connected: ${conn.connection.host}`)
}
catch (error) {
console.log(error)
process.exit(1)
}
}
module.exports = connectDB
Mongo URI is in .env file, but you can replace it with your connection string (but more secure in .env file)
Then in server.js or index.js (entry file)
const connectDB = require('path_to_file')
connectDB()
I Tried this approach !! May be it could be helpful.
DBconn.js (MONGO_URL is from .env file & dev_db_url is optional here)
require('dotenv').config({ path: 'env/.env' });
const dev_db_url = 'local dev. db url is not defined.';
const mongoDB_URL = process.env.MONGO_URL || dev_db_url;
const dbOptions = {useNewUrlParser: true, useUnifiedTopology: true};
const connectDB = async (cb) => {
try {
await mongoose.connect(mongoDB_URL, dbOptions)
.then(() => {
cb();
console.log("Connected to Database");
})
} catch (error) {
console.error("Could not Connect to Database", error)
}
};
module.exports = connectDB;
Server.js (Server will start to listen only after successful DB Connect)
require('dotenv').config({ path: 'env/.env' });
const connectDB = require('./database/DBConn')
const port = process.env.PORT || 5000;
const express = require('express')
const app = express()
// Connecting to DB
connectDB(()=>{
app.listen(port, () => {
console.log(`Backend : NodeJS/express server started on http://localhost:${port}`)
})
});
Another Way :
DBconn.js
const mongoose = require("mongoose");
require('dotenv').config({ path: 'env/.env' });
const dev_db_url = 'local dev. db url is not defined.';
const mongoDB_URL = process.env.MONGO_URL || dev_db_url;
const dbOptions = {useNewUrlParser: true, useUnifiedTopology: true};
const connectDB = async () => {
try {
await mongoose.connect(mongoDB_URL, dbOptions);
} catch (error) {
console.error("Could not Connect to Database", error)
}
};
module.exports = connectDB;
Server.js (here we use .once method)
require('dotenv').config({ path: 'env/.env' });
const mongoose = require("mongoose");
const connectDB = require('./database/DBConn')
const port = process.env.PORT || 5000;
const express = require('express');
const app = express();
connectDB();
mongoose.connection.once('open', () => {
console.log('Connected to MongoDB');
app.listen(port, () => {
console.log(`Backend : NodeJS/express server started on http://localhost:${port}`)
})
});

How a express to pass object to other file?

In app.js, when express running, express will create pool connection. then pool instance can be access in other file. How to do that?
app.js
const express = require('express');
const app = express();
const port = 8080;
const mysql = require('mysql2');
const comic = require('./routes/comic');
app.use('/comics', comic);
app.listen(port, () => {
console.log(`Server is listening in ${port} port`);
const pool = mysql.createPool({
host:'localhost',
user: 'root',
password: 'test',
database: 'test'
});
exports.connection = pool.promise();
});
test.js
const {connection} = require('./app');
(async () => {
const [rows] = await connection.execute('SELECT * FROM people');
console.log(rows);
})();
I would recommend you to have a seperate db.js file that would have the connection pool and import that pool wherever necessary
In db.js
const mysql = require('mysql2');
const pool = mysql.createPool({
host:'localhost',
user: 'root',
password: 'test',
database: 'test'
});
module.exports = pool;
And in the place where u want it
let pool = require('./db');
const queryRes = (query, pool) => new Promise((resolve, reject) => {
pool.getConnection(function(err, connection) {
if(err) {
reject('Error');
}
connection.query(query, (err, results, fields) => {
if(err) {
reject('Error');
}
else{
connection.release();
resolve(results);
}
});
connection.on('error', (err) => {
reject('Error');
connection.release();
});
});
});
queryRes("Select * from test", pool).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});

How could I make a global mongodb connection that I can access from other files

So I have this main server file index.js:
const express = require('express')
const app = express()
const route = require('./route')
app.use('/main', route)
app.listen(3000)
and then I have the route.js file:
const express = require('express')
const router = express.Router()
router.get('/', (req, res) => {
res.send('Hello from main')
})
module.exports = router
As the title implies, how could I make a global mongodb connection so that I don't have to make a new connection to the database on every route?
Thanks!
I'm surprised there is no answer on SO to this. The most common pattern is to initialize your database connection in a separate module and to import it in any file that needs it.
The below was taken from this longer article https://itnext.io/how-to-share-a-single-database-connection-in-a-node-js-express-js-app-fcad4cbcb1e and was written in callback style. I've updated it a little to be promise based below:
/* Callback Style */
const assert = require("assert");
const client = require("mongodb").MongoClient;
const config = require("../config");
let _db;
module.exports = {
getDb,
initDb
};
function initDb(callback) {
if (_db) {
console.warn("Trying to init DB again!");
return callback(null, _db);
}
client.connect(config.db.connectionString,
config.db.connectionOptions, connected);
function connected(err, db) {
if (err) {
return callback(err);
}
console.log("DB initialized - connected to: " +
config.db.connectionString.split("#")[1]);
_db = db;
return callback(null, _db);
}
}
function getDb() {
assert.ok(_db, "Db has not been initialized. Please called init first.");
return _db;
}
/******************************************************************/
//The client
const initDb = require("./db").initDb;
const getDb = require("./db").getDb;
const app = require("express")();
const port = 3001;
app.use("/", exampleRoute);
initDb(function (err) {
app.listen(port, function (err) {
if (err) {
throw err; //
}
console.log("API Up and running on port " + port);
});
);
function exampleRoute(req, res){
const db = getDb();
//Do things with your database connection
res.json(results);
}
Here's a promise based version without semi-colons which is how I might do it for itself. These functions would all become candidates for reuse between projects.
const assert = require("assert")
const client = require("mongodb").MongoClient
const config = require("../config")
let _db
module.exports = {
getDb,
initDb
}
function initDb() {
if (_db) {
console.warn("Trying to init DB again!");
return Promise.resolve(true)
}
return client.connect(config.db.connectionString,
config.db.connectionOptions)
}
function getDb() {
assert.ok(_db, "Db has not been initialized. Please called init first.")
return _db
}
//////////////////////
const {initDb, getDb} = require("./db")
const app = require("express")()
const port = 3001
app.use("/", exampleRoute)
initDb().
then(_ =>bootServer(port))
.catch(console.log)
function bootServer(port) {
app.listen(port, function (err) {
if (err) {
Promise.reject(err)
}
console.log("API Up and running on port " + port)
Promise.resolve()
})
}
function exampleRoute(req, res){
const db = getDb();
//Do things with your database connection
res.json(results);
}

Mongoose & MongoDB connection on production

What are best practicies to handle mongodb connection using mongoose on production?
This is my code
connectToDatabase.js
'use strict';
const mongoose = require('mongoose');
const mongodb = require('mongodb');
mongoose.Promise = require('bluebird');
const { Db, Server } = mongodb;
const database = 'test';
const connectToDatabase = (callback) => {
if (process.env.NODE_ENV == 'test') return false;
const db = new Db(database new Server('localhost', 27017));
db.open()
.then(() => {
mongoose.connect(`mongodb://localhost/${database}`, { config: { autoIndex: false } });
mongoose.connection
.once('open', () => {
console.log(`Connected to database ${database}`);
callback(db);
})
.on('error', (error) => {
console.warn('Warning', error);
});
});
};
module.exports = connectToDatabase;
app.js
const connectToDatabase = require('./connectToDatabase');
connectToDatabase(() => {
// run server
});
I don't know exactly what happening when connection to database is interrupted, Is mongoose trying connect to database again?

Resources