I am using using NodeJS and MongoDb as a backend service in my android application.I want to know how can I pool connections so that it minimize the load on server and make fast operations and how to close the connection
to database after performing operation.
This is what I have been done so far:
const express = require('express');
const bodyParser = require('body-parser');
const env = require('dotenv').config();
const MongoClient = require('mongodb').MongoClient;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.post('/add', (req,res) => {
var data = {
User_id: req.body.userId,
Email:req.body.email,
Name: req.body.name,
Book_name: req.body.bookName,
};
MongoClient.connect(dburl, {useNewUrlParser:true} ,(err,client) => {
if(err){
console.log("Error".red, +err);
}
else{
var collect = client.db('Mydb').collection('Books');
collect.insertOne(data, (err,resp) =>{
if(err){
console.log("Error", +err);
}
else{
console.log("Successfully inserted");
}
client.close();
});
}
});
});
app.listen(port,() => {
console.log("App is running on:" +port);
});
Someone please let me know what else need to be added in above code to achieve desired results.Any help would be appreciated.
THANKS
MongoClient by default sets up a connection pool of size 5. You can initiliaze the connection and reuse it.
let connection;
MongoClient.connect(dburl, {useNewUrlParser:true} ,(err,client) => {
if(err){
console.log("Error".red, +err);
}
connection = client;
// maybe move your app.listen here to make sure server is started after connection is acquired or something equivalent
})
// elsewhere after connection is established:
connection.db('Mydb').collection('Books');
To increase/decrease the pool size you can pass the poolSize option with the required number.
Related
I was familiar with MongodB for CRUD operation. Here, I'm trying to make simple post request on mongodB atlas but I want to know where I have done error for the connection and posting data to MongodB atlas.
Model.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
let quizSchema = new Schema({
title: {
type: String,
},
description: {
type: Number,
},
question: {
type: String,
},
});
const Quiz = mongoose.model("Quiz", quizSchema);
module.exports = Quiz;
index.js
I'm trying to create the database collection name "QuizDatabase" and insert the data to it.
var express = require("express");
var bodyParser = require("body-parser");
const Quiz = require("./views/model/model");
var Request = require("request");
var app = express();
app.use(bodyParser.json());
const MongoClient = require("mongodb").MongoClient;
const uri =
"mongodb+srv://username:password#cluster0.iom1t.mongodb.net/QuizDatabase?retryWrites=true&w=majority";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
mongoose.connect(uri);
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
app.post("/new/", function (req, res) {
Quiz.collection("QuizDatabase").insertMany(req.body, function (err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new quiz.");
} else {
res.status(201).send(JSON.stringify(body));
}
});
});
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({ error: message });
}
You dont have to use mongo client if you are already using mongoose.
In index.js file just import the model
const Quiz = require("./model");
And you are already using mongoose to connect to db when you write mongoose.connect(uri); You don't have to use client.connect() again.
Query to insert -
Quiz.insertMany(req.body);
Your index file should look like this -
const Quiz = require("./views/model/model");
var Request = require("request");
var app = express();
app.use(bodyParser.json());
const uri =
"mongodb+srv://username:password#cluster0.iom1t.mongodb.net/QuizDatabase?retryWrites=true&w=majority";
mongoose.connect(uri);
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
app.post("/new/", function (req, res) {
Quiz.insertMany(req.body, function (err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new quiz.");
} else {
res.status(201).send(JSON.stringify(body));
}
});
});
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({ error: message });
}
There are several reasons.
Connection Issues to the MongoDB database.
To check this insert app.listen() into mongoose connect. This would make sure you can only run development on your preferred PORT only when it has successfully connected to your Database. e.g From your code
mongoose.connect(uri)
.then(() => {
//listen for PORT request
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
}).catch((error) => {
console.log(error);
});
Try purposely using the wrong Username or Password and see if you get this error:
MongoServerError: bad auth : Authentication failed.
at Connection.onMessage (/Users/user/Documents/..<pathway>../connection.js:207:30)
*
*
*
*
ok: 0,
code: 8000,
codeName: 'AtlasError',
[Symbol(errorLabels)]: Set(1) { 'HandshakeError' } }
If you don't get this error then you have a connection problem. To solve this, I added my current IP ADDRESS and 0.0.0.0/0 (includes your current IP address) at the Network Access page. So you click on MY CURRENT IP ADDRESS and confirm upon setting up the network. Go to NETWORK ACCESS, click on add new IP ADDRESS, input 0.0.0.0/0 and confirm. Then try using the wrong username or password in the URI link given to you to see if it gives the above-expected error, then you can now correct the Username and Password, and npm run dev or npm start (However you configured it in your package.json file).
Code issues
First of I would correct your Model.js file from this:
const Quiz = mongoose.model("Quiz", quizSchema);
module.exports = Quiz;
to this:
module.exports = mongoose.model("Quiz", quizSchema);
I can see why yours can work, but it may be an issue as you want to get the schema upon accessing the whole file.
Secondly, I would correct the code for Posting and you can do that in 2 ways using the asynchronous method. Which depends on the method of assigning the req.body.
Way 1:
app.post("/new/", async (req, res) => {
const { title, description, question } = req.body;
//adds doc to db
try {
const quiz = await Quiz.create({ title, description, question });
res.status(200).json(quiz);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
OR
Way2:
app.post("/new/", async (req, res) => {
const quiz = new Quiz(req.body);
//adds doc to db
try {
const savePost = await quiz.save();
response.status(200).send(savePost);
} catch (error) {
response.status(400).send(error);
}
});
NOTE: You don't necessarily have to create a named database and collection in Mongo Atlas before starting the project. The URI given to you covers that if there are no problems with the connection to the DB or the Code.
based on your code
URI:
"mongodb+srv://username:password#cluster0.iom1t.mongodb.net/QuizDatabase?retryWrites=true&w=majority";
would create a database called: QuizDatabase and collection called: quizs (MongoDb always creates the plural word from the model given and makes it start with lowercase (i.e from your Model.js, the mongoose.model("Quiz"))).
If no database is named in your URI, then a database called test is automatically created for you as a default database, with the collection name being the mongoose.model("") given.
CONCLUSION
This should solve at least 90% of your issues, any other creation/POST problems is currently beyond my current expertise. Happy Coding 🚀🚀🚀
This question already has answers here:
How to properly reuse connection to Mongodb across NodeJs application and modules
(25 answers)
Closed 3 years ago.
I am learning to use the mongodb native driver along with nodeJS and ExpressJS. I am new to NodeJS so please bear with me.
The UI CLIENT sends data to the REST API endpoint and the POST call inserts the data (document) into MongoDB collection.
When I am going through the examples at MongoDB native driver documentation, I notice that collection.insertOne, collection.save are always performed as a callback to the mongo_client.connect. I don't understand this because I want to connect to mongo_client once and continue to update the collection and bring down the connection (mongo_client.close) when the express server is brought down. I understand that callbacks are safe.
const client = new MongoClient(url, {useNewUrlParser: true});
// Use connect method to connect to the server
client.connect(function(err) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
insertDocuments(db, function() {
client.close();
});
});
Why do I have to connect for every CRUD operation? save the state of the connection to the db/collection and cannot reuse?
My existing code:
const express = require('express')
const app = express()
const server_port = 64726
const MongoClient = require('mongodb').MongoClient;
const insert_user = (id, email)=> {
mongo_client.connect(err => {
console.log("mongo connect function called....")
assert.equal(null, err)
console.log ("connected successfully to DB ")
const mongo_user_collection = mongo_client.db(mongo_db_name).collection("users");
mongo_user_collection.save ({'_id':id,'email':email,'lastlogin': new Date() })
// perform actions on the collection object
// mongo_client.close();
});
}
app.post ('/api/login/verify', (req, res) => {
insert_user(req.body.id,req.body.email);
})
app.listen(server_port, ()=>{
console.log('Server started...')
})
In my code, I see for every post call I need to connect and then insert the document. How to avoid this behavior so I can Connect once, reuse connection and insert docs for every POST call?
This worked for me. Thanks all for the suggestions.
const mongo_client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
let mongo_user_collection;
mongo_client.connect(err => {
console.log("mongo connect function called....")
assert.equal(null, err)
console.log ("connected successfully to DB ")
mongo_user_collection = mongo_client.db(mongo_db_name).collection("users");
});
const insert_user = (id, email)=> {
mongo_user_collection.save ({'_id':id,'email':email,'lastlogin': new Date() })
}
app.post ('/api/login/verify', (req, res) => {
insert_user(req.body.id,req.body.email);
})
app.listen(server_port, ()=>{
console.log('Server started...')
})
i have a nodejs server which is getting list of a collection from mongodb . Here is its code . since am new to sockets so ..
const express = require("express");
const app = express();
const http = require("http").Server(app);
const socketio = require('socket.io');
after that iam simply getting data in a route . and one thing more all code is in one file and i do need express route as there are other routes in app. here is the mongodb code for getting list
app.post("/getAllOfferManagement",
async (req, res) => {
try {
MongoClient.connect(url,
function(err, db) {
if (err) throw err;
var dbo = db.db("realtime");
dbo
.collection("offer")
.find({})
.toArray(function(err,
result) {
if (err) throw err;
// console.log('getting it ');
res.send(result);
db.close();
});
});
} catch (err) {
res.send("error");
}
}); // its all working fine when i hit the route
http.listen(5000, function() {
console.log("Server Started!");
});
//serversidecode ends here
Now am getting the data through angular and here is the code for it
$scope.getAllOffer = function() {
$scope.mongoloader = true;
//nodejs api endpoint
$http.post("http://localhost:5000/getAllOffer").then(function(res) {
$scope.offersArray = res.data;
console.log('data here', res.data);
});
};
the above works fine . but i need to get data in realtime e.g when somone insert new doc in mongodb the the view get updates . am new to sockets so any help is appreciated. Thanks
For this u have to add an event to backend and as well as in frontend
Backend
io.on('connection', (socket) => {
console.log(socket.id);
socket.on('SEND_TITLE', function(data){
io.emit('RECEIVE_TITLE', data);
console.log('data',data)
})
});
For frontend u have to use socket io client module
import io from "socket.io-client";
socket = io('your backend host url')
socket.on('RECEIVE_TITLE', function(data)
Console. Log(data);
});
Frontend syntax could differ in angular.
As I am not familiar with angular
For more information visit.
Forclient side.
https://socket.io/docs/client-api/
For server.
https://socket.io/docs/server-api/
I have deployed an application on Zeit Now using ExpressJS. The application makes a connection to MongoDB using Mongoose. However, the state of the connection, which I obtain using mongoose.connection.readyState is displayed as 2, which denotes 'connecting'.
I tried running the application locally and it works fine, where I am able to write to the database.
const connectionURL = "mongodb+srv://MONGODB_USERNAME:MONGOD_BPASSWORD#cluster1-23abc.mongodb.net/DATABASE_NAME?retryWrites=true"
expressApp.listen(3000, function() {
console.log("Listening to port 3000");
});
mongoose
.connect(
connectionURL, { useNewUrlParser: true }
)
.then(function() {
console.log("db connected!");
});
expressApp.get("/", function(req, res) {
res.write(`Connection State: ${mongoose.connection.readyState}\n`);
res.end();
});
I would expect mongoose.connection.readyState to be 1, which denotes 'connected'.
However, mongoose.connection.readyState is stuck at 2, which denotes 'connecting'.
Also, now logs does not show any errors.
You'll want to cache your MongoDB connection so you won't have to make a new connection on each lamda call.
You can make an lib folder and empty mongoose.js file (lib/mongoose.js) as I did and place this code inside:
`import mongoose from 'mongoose';
let cachedDb = null;
console.log('outside-cachedDB:', cachedDb);
async function connectToDatabase(uri) {
if (cachedDb) {
console.log('=> using cached database instance');
return cachedDb;
}
// If no connection is cached, create a new one
const db = await mongoose.connect(uri, { useNewUrlParser: true });
console.log('New MongoDB Connected');
// Cache the database connection and return the connection
cachedDb = db;
return db;
}
export default async () => {
await connectToDatabase(process.env.MONGODB_URI);
};`
Then call this custom mongoose function in any lamda that needs a mongoDB connection:
`import express from "express";
import mongoose from "../lib/mongoose";
const app = express();
// #route Get api/connect
// #desc Tests post route
// #access Public
app.get("*", async (req, res) => {
await mongoose();
// Code to query your DB or whatever here
});
export default app;`
You don't have to use express of course, but I personally haven't moved on to newer solutions. One of these days I'll learn micro.js.
I am getting started with mongoDB and I have to say that the official documentation is not that great to see how to implement it with nodejs.
I don't really know how to structure my server file to add mongoClient.connect, should my whole server be written inbeetwen the mongoClient.connect function in order to have access to the db, like in this boilerplate? I am using nodeJS/express.
If you know any good boilerplate, or anything, that could show me the structure of a backend with an implementation of mongoDB, I would really appreciate it. Every time I find something about mongoDB, it is actually about mongooooose!!
After further reasearch, here is what I was looking for, for those who wonder like me how to implement MongoDB (and not mongoose) with Express:
var express = require('express');
var mongodb = require('mongodb');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var db;
// Initialize connection once
MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, database) {
if(err) throw err;
db = database;
// Start the application after the database connection is ready
app.listen(3000);
console.log("Listening on port 3000");
});
// Reuse database object in request handlers
app.get("/", function(req, res) {
db.collection("replicaset_mongo_client_collection").find({}, function(err, docs) {
docs.each(function(err, doc) {
if(doc) {
console.log(doc);
}
else {
res.end();
}
});
});
});
I've found several ways of doing it, even in mongoDB's official pages.
By far, I prefer this one (not mine, source below) where you instantiate the connection in one file and export it and the database/client to the server file where express is instantiated:
(I copied only what's important, without error handling)
// database.js
const MongoClient = require('mongodb').MongoClient;
let _db; //'_' private
const mongoConnect = function(callback) {
MongoClient.connect(
'mongodb://localhost:27017',
{ useUnifiedTopology: true }
)
.then(client => {
_db = client.db('onlineshopping');
callback();
})
.catch(error => {
console.log(err);
throw new Error('DB connection failed...');
});
}
const getDB = () => {
if (_db) {
return _db;
} else {
throw new Error('DB connect failed');
}
}
exports.mongoConnect = mongoConnect;
exports.getDB = getDB;
// index.js
const express = require('express');
const app = express();
const mongoConnect = require('./util/database').mongoConnect;
// ...
mongoConnect(() => {
app.listen(3000);
})
Source:
https://github.com/TinaXing2012/nodejs_examples/blob/master/day9/util/database.js
Corresponding to this YouTube course that I recommend in this topic: https://www.youtube.com/watch?v=hh-gK0_HLEY&list=PLGTrAf5-F1YLBTY1mToc_qyOiZizcG_LJ&index=98
Other alternatives from mongoDB official repos, are:
https://github.com/mongodb-developer/mern-stack-example
https://github.com/mongodb-developer/nodejs-quickstart