Create new database with API call - node.js

I want to create a new database at the time of the API call. I am already connected to one main database.
I have tried using mongoose.connect() method. And it gives me a positive response. But when I checked in mongo console I did not find the newly created database.
Here is my code.
const connectionString = `mongodb://${process.env.DB_HOST}:${
process.env.DB_PORT
}/client_${Math.random()
.toString(36)
.substring(2, 8)}`;
mongoose.connect(
connectionString,
{
autoReconnect: true,
reconnectTries: 60,
reconnectInterval: 10000,
useNewUrlParser: true,
useCreateIndex: true
},
(error) => {
if (error) {
console.log(error);
} else {
console.log('Connected');
}
}
);
Hope you got my point. Looking for a solution.

As per mongodb documentation:
If a database does not exist, MongoDB creates the database when you first store data for that database. As such, you can switch to a non-existent database and perform the following operation in the mongo shell. link
This is true for mongo-shell as well, if you do use mydb; to create one and immediately do show dbs; it won't show up unless you create some data for that mydb like createCollection(), insert() etc.
So your code is alright because connect() is as good as use db;. Unless you create some data for that db you won't see that in mongo console.

Related

Managing MongoDB databases connection Based on Users

Good Morning Everyone .
for my project I'm Using mongo Atlas DB + Nodejs + express js
Currently let say I have one customer and all his users(managed with local-passport-js) and data are managed inside one DB in my cluster.
I'm Interested managing my project a step forward and create multiple DB's one for each costumer .
every costumer will have a different DB managing his users and data.
this is my current connection to the Db:
const MongoUrl = `mongodb+srv://*myuser**:${process.env.password}#testdb.9unfjt9.mongodb.net/?retryWrites=true&w=majority`
mongoose.connect(MongoUrl,
{ useNewUrlParser: true, useUnifiedTopology: true})
.then(()=> {
console.log('DB Connection, Successful')
})
.catch(err => {
console.log('Error connecting DB')
console.log(err)
})
How can I Create "Global" User Collection and determine which DB the user Associate to and load it.
Thanks !

TypeError: Cannot read property 'find' of undefined when deployed but not locally

I have created a MongoDB Atlas Cluster, put some data in there, then created a node/express app to retrieve data from that cluster. Locally I am able to retrieve the correct data but when my node server is deployed to AWS Elastic Beanstalk, I get this error:
TypeError: Cannot read property 'find' of undefined
I'm unsure of how to even trace this problem I am having.
const MongoClient = require('mongodb').MongoClient;
let database;
MongoClient.connect(
'url-to-cluster',
{useNewUrlParser: true, useUnifiedTopology: true},
(err, client) => {
const users = client.db('entity');
database = users.collection('entityinfo');
});
// Used in app.use method
database.find().toArray()
.then(results => {
res.json(results[0].UID);
});
The call to MongoClient.connect is asynchronous, it will return immediately and call the provided callback only after the connection resolves.
To demonstrate this, add log messages before the call to connect, inside the callback, and before the call to find. I believe you will discover that find is being called before the callback that would give database a value.
This likely works locally because the connection completes fast enough that is it done before find is called, but takes several milliseconds (perhaps tens of milliseconds) when connecting to the server in the cloud. i.e. this is a race condition.
You might try including the find call inside the callback, like
MongoClient.connect(
'url-to-cluster',
{useNewUrlParser: true, useUnifiedTopology: true},
(err, client) => {
const users = client.db('entity');
database = users.collection('entityinfo');
// Used in app.use method
database.find().toArray()
.then(results => {
res.json(results[0].UID);
});
});

Should I be concerned with mongoose/mongodb and its amount of 'connections' being made/held?

Overview:
I have built a production forum software and I am growing concerned with 'current connections' and scale-ability and I recently refactored how my database handles connections which may be incorrect?
Atlas:
I am using mongoDB atlas, and I recently got a warning for 'maximum connections' (at 100) and I upgraded the server but it is of great concern with only a small production use but the amount of connections (and growing) that scaling seems like it'll be problematic
Attempted solution:
I tried to dispose of connections as soon as the query was over.
const connectMongoDB = (req, res, next) => {
// Add setting to stop creating connection if no mongo query is being made within the route
if (mongoose.connection.readyState === 1) return next();
mongoose.connect(config.database.mongo.connection, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
socketTimeoutMS: 50000,
reconnectTries: 30,
reconnectInterval: 1000,
}, () => next());
};
const disconnectFromMongoDB = (req, res, next) => {
res.on('finish', () => setTimeout(() => mongoose.connection.close(), 2000));
return next();
};
These are middleware, one runs before and after a route respectively, the timeout was needed as sometimes (not consistently reproducible) mongoose would error out with 'topology destroyed' and this timeout fixed this issue. I believed this would fix the issue, but my connections are steadily growing in atlas (175, at a max of 350), as shown below.
Another concern is command vs query amount as seen here
I worry my connection management is wrong and/or the database scaling is way greater than I initially thought.
I also close the connection on the process EXIT as advised, but this seems to be a very intimidating problem, feels with such a reasonably small production environment, that this increase is intimidating to say the least
Any advice
some of my queries include;
Is this something ive caused with bad connection management?
Can this be eleviated/fixed programmantically
Did I pick potentially the wrong database type (NoSQL)
Is this a problem with atlas/does atlas not scale in an ideal manner VS hosting on a bunch of VPS etc or another mongo host provider
I guess you have a problem with the use of mongoose. You only need to call the mongoose.connect when your program init. And then use the models to do the CRUD operations. Here is the simple example from the mongoose docs:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Cat = mongoose.model('Cat', { name: String });
const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));
Also, you can set the poolSize options to limit the connections to your mongo server

How should I connect and move my local mongoose db to mongodb cloud atlas?

When I start my server, an error was shown like this:
Error in DB connection : Error: queryTxt ETIMEOUT yky-api-ajgvf.mongodb.net
I tried many times to work properly in order to fix this problem. I couldn't even deploy my project on heroku properly yet. I love nodejs so much but now I just want to give up continuously learning Nodejs for now.
Someone help me to solve my problem if possible. I'm the one who is learning Node.Js. It's been around 4 or 5 months. Before I decided to leran PHP, but now I'm still trying to learn nodejs.
I'm a newbie. :)
This is my config database code in my small project.
const mongoose = require('mongoose')
const log = console.log
mongoose.connect('mongodb+srv://chanlay:chanlay123#yky-api-ajgvf.mongodb.net/yky-blog-api?retryWrites=true&w=majority', {
useNewUrlParser: true
}, (err) => {
if (!err) {
log('MongoDB Connection Succeeded.')
} else {
log('Error in DB connection : ' + err)
}
});
require('../models/posts')
mongoose.connect() can look like this (docs reference):
mongoose.connect(uri, options, function(error) {
// Check error in initial connection. There is no 2nd param to the callback.
});
// Or using promises
mongoose.connect(uri, options).then(
() => { /** ready to use. The `mongoose.connect()` promise resolves to mongoose instance. */ },
err => { /** handle initial connection error */ }
);
Before demonstrating further, first of all, this block of yours is wrong:
if (!err) {
log('MongoDB Connection Succeeded.')
}
error handling doesn't work that way, this condition will never happen, as when there's no error, there is no reason to call error callback function which checks this condition.
Instead use .then() block, as a successful connection returns a Promise:
mongoose.connect(uri, options).then(
() => { console.log('MongoDB Connection Succeeded.') },
err => { console.log(err) }
);
// OR use .catch() after .then()
mongoose.connect(uri, options).then(() => console.log('MongoDB Connection Succeeded.')).catch( err => console.log(err))
Your answer: set socketTimeoutMS to 60000 or 90000.
If still didn't work, add connectTimeoutMS=90000 and reconnectTries=1000 to options too.
Declare a new variable named options (the name is arbitrary, but better follow the convention), and you put your useNewUrlParser: true also there (reference):
const options = {
useNewUrlParser: true,
socketTimeoutMS: 60000 //or 90000
}
Tip: You can also specify driver options in your connection string as parameters in the query string portion of the URI (reference):
{main-url}?socketTimeoutMS=90000, that is:
const uri = mongodb+srv://chanlay:chanlay123#yky-api-ajgvf.mongodb.net/yky-blog-api?retryWrites=true&w=majority?socketTimeoutMS=90000
but stick with options variable as it's cleaner, more readable, and easier to maintain (otherwise you would put everything in a string which makes it harder for you to read and debug).
Please let me know by leaving to my answer a comment either as a feedback or reporting the persistent error.

How to connect to mongoDB Atlas using mongoose

I'm trying to connect to my cluster on mongoDB Atlas via Mongoose.connect(), but every time i try to connect i get an exception "MongoError: authentication fail"
I know MongoDB Atlas is new mongo as a service could it be not supported by mongoose yet?.
The answer in this related post is correct. You should:
not mix options with connection string (if done so)
make sure your IP you are running on is whitelisted and your network allows connections to Atlas
make sure the user has sufficient permissions
use the connection string as is provided by atlas and just provide it to
mongoose.connect(uri);
MongoError: authentication fails - It means your name or password or dbname is not correct -
uri sample -
const uri =
"mongodb+srv://<username>:<password>#firstcluster.4rc4s.mongodb.net/<dbname>?retryWrites=true&w=majority";
Suppose username is - najim & password is 1234 & dbname is pets (Note - default dbname is test but you can write whatever you want) then my uri will be with above credentails -
const mongoAtlasUri =
"mongodb+srv://najim:1234#firstcluster.4rc4s.mongodb.net/pets?retryWrites=true&w=majority";
to connect with moongoose
try {
// Connect to the MongoDB cluster
mongoose.connect(
mongoAtlasUri,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log(" Mongoose is connected")
);
} catch (e) {
console.log("could not connect");
}
const mongoAtlasUri =
"mongodb+srv://<username>:<password>#firstcluster.4rc4s.mongodb.net/<dbname>?retryWrites=true&w=majority";
try {
// Connect to the MongoDB cluster
mongoose.connect(
mongoAtlasUri,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log(" Mongoose is connected"),
);
} catch (e) {
console.log("could not connect");
}
const dbConnection = mongoose.connection;
dbConnection.on("error", (err) => console.log(`Connection error ${err}`));
dbConnection.once("open", () => console.log("Connected to DB!"));
try {
mongoose.connect( uri, {useNewUrlParser: true, useUnifiedTopology: true}, () =>
console.log("connected"));
}catch (error) {
console.log("could not connect");
}
this works fine , try it
"mongodb+srv://:#cluster0.vvkuk.mongodb.net/"
also in the atlas, in security go to network access, there will be small buttons edit and delete click on edit, and in the edit, there will to two options the first option is ADD CURRENT IP ADRESS & the second option will be ALLOW ACCESS FROM ANYWHERE
go for the first option & then click confirm

Resources