I am working on a project that requires a dedicated database per registered user. I prefer working with MongoDB so I'm using that for the same (Am I Right?). The app uses a REST API as the backend (written in Node Express) and an AngularJS App. So, what I think of doing is whenever a user makes a request to some API endpoint say, a GET request to api/user/mydata, I would create a connection to his particular database, fetch the required data, close the connection and return the fetched data as the response. Is this approach correct? Also, I'm using Mongoose as the ODM and PassportJS for user Authentication. Moreover, users of my app are mutually exclusive. There is no data connection between a user with any other registered user.
There's a way to do that but only without using Mongoose. You would have to create a root connection to your MongoDB server (mind it, not to a particular database on that server) using the mongodb node module and then you can switch between the database as per your query requirement without creating a new connection per database as shown below:
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
// URL to the root of MongoDB Server and not a particular db
const url = 'mongodb://localhost:27017';
// Database Names
const dbName1 = 'myproject1';
const dbName2 = 'myproject2';
// Use connect method to connect to the server
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db1 = client.db(dbName1);
const db2 = client.db(dbName2);
client.close();
});
You can't do this through mongoose, as mongoose and its models require connection to be made to a particular database and not to just the root db server. Anyways, I didn't want to give up mongoose for my own project so I just had to resort to initializing the db connection and its models per HTTP request by the user and closing the connection upon response.
Related
I am working on an application that needs to connect to different MongoDB databases based on the customer that is accessing my application. Each MongoDB database is located on separate servers.
For example, if my application has 3 different customers:
john (mongodb://john:john#server1/john)
tom (mongodb://tom:tom#server2/tom)
harry (mongodb://harry:harry#server3/harry)
when john uses my application, Express.js should connect to mongodb://john:john#server1/john or when harry uses my application, it should connect to mongodb://harry:harry#server3/harry.
I am wondering what an optimized way would be to achieve this. Normally, when we have just one MongoDB database instance, we put the mongoose.connect method inside the app.js and that gets called when the Express.js server starts, but in this case I don't want to connect all three databases at once since that will not be the optimized way.
According to the Mongoose docs, it does support connections to multiple hosts.
const conn1 = mongoose.createConnection('host1', options)
const conn2 = mongoose.createConnection('host2', options)
Let me give you an example (this is Express code) :
// CONNECTION SETTER MIDDLEWARE
app.use(async function (req, res, next) {
// Let's just assume you identified the user earlier with your favourite
// auth method and put their identity in req.user
const userCon = await mongoose.createConnection(`mongodb://${req.user.username}:${req.user.password}#${req.user.host}/${req.user.database}`) // Here you have it!
// Saving the connection in the request so the next
// middlewares/handlers can access it
req.user.connection = userCon
// Thank you, next (middleware/handler)
next()
});
While mongoose.connect() sets the default connection, mongoose.createConnection() only returns a connection.
This is what I would try, and this is Mongoose's recommended way to handle multiple connections. You should note that you can't share Models across different connections, but you can share Schemas.
If you want to just initialize the connection and connect later, the Mongoose docs also provide an example.
// initialize now, connect later
db = mongoose.createConnection();
db.openUri('localhost', 'database', port, [opts]);
I'm using node.Js, expressjs mongodb and Atlas
var Db = require('mongodb').Db;
var Server = require('mongodb').Server;
the above method is not working for me.
by using atlas database. you are given three nodes with three different host/Url now the problem here is that when I try to connect to mongodb.server it only ask for one host name (or its allowed to add many but I just don't know how)
my question would be, how can I make this work? like how can I join together 3 different Url and let 1 port let it in. and connect to database server
you are given three nodes with three different host/Url now the problem here is that when I try to connect to mongodb.server it only ask for one host name
MongoDB Atlas provides you with a MongoDB Connection URI. The connection string should contain host(s) information.
You can also see a snippet example of MongoDB Node.js connecting to MongoDB Atlas on the manual MongoDB Atlas: Node.js Driver Example
MongoClientURI uri = new MongoClientURI(
"mongodb+srv://user:password#cluster0.mongodb.net/");
MongoClient mongoClient = new MongoClient(uri);
MongoDatabase database = mongoClient.getDatabase("databaseName");
MongoDB Version 3.4 and earlier:
var MongoClient = require('mongodb').MongoClient;
var uri = "mongodb://user:password#mycluster0-shard-00-00.mongodb.net:27017,mycluster0-shard-00-01.mongodb.net:27017,mycluster0-shard-00-02.mongodb.net:27017/admin?ssl=true&replicaSet=Mycluster0-shard-0&authSource=admin";
MongoClient.connect(uri, function(err, db) {
db.close();
});
For other drivers, please see MongoDB Atlas: Connect via Driver
I am trying to implement a feature which a user can decide on login to which DB to connect. As it is a web-app, running on a server which all the clients approach, how can I implement this feature without changing every client DB?
At our company we are using mongoose as the MongoDB API.
I read all the docs, and didn't notice any functionality for using multiple connections to different DB's on different hosts within the same App at once - without damaging other's client work.
The most valuable thing I have accomplished is to open few connections based on multiple mongoose instances, based on this post:
Mongoose and multiple database in single node.js project
I have created few files for example:
var mongoose = require('mongoose');
mongoose.createConnection('mongodb://10.20.100.71:27017/DB_NAME');
module.exports = exports = mongoose;
And then I required them:
let stageAccess = require('./databsesConnections/stageAccess');
let prodAccess = require('./databsesConnections/prodAccess');
I debugged the files and checked the connections are establishing.
Further more I checked in the mongoose docs and concluded that I can choose which connection is the default connection, as the docs state:
"Mongoose creates a default connection when you call mongoose.connect(). You can access the default connection using mongoose.connection."
So I tried:
mongoose.connection = mongoose.connections[1];
And it works fine.
So the actual question is, what will happen if client 1 approach the app, select to connect dbNum1 and starts to work,
then client 2 approach the app and select to connect to dbNum2?
I have a node program connecting to a MongoDB. Theres a production server where we do proper authentication to connect to the db, but during development on our local machines it's just more tedious to keep track of authentication, especially because most of the time we completely wipe the db often. So resetting up authentication becomes even more tedious. So my solution was to attempt to connect to the db securely, and then if it fails then try to connect to the db in the dev fashion. Heres the code:
var db = require('monk')('username:password#localhost/TESTR', {authSource:'admin'});
db.catch(function(err) {
clog.i("MONGO AUTHENTICATION FAILED, USING NO AUTH CLIENT");
db = require('monk')('localhost/TESTR')
});
The problem is that this doesn't work. The rest of the app just complains about the authentication failure the first attempt had. Is there a better solution to this? Or am I just a moron?
var monk = require('monk');//layer used to connect mongodb
var db = monk('*****:27017/TESTR');
var collection = db.get('collection_name');
//you can access your collection using the mongo query
//simple controller action
module.exports = function(req, res){
collection.find({}, function(err, cb){
if(err) {res.json("db exception");}
else{res.json(cb)//it returns the db collections}
};
}
I have two node.js applications, both of them should connect to the same mongodb database. I should insert document in one application and retrieve it from the other application. I added the same connection of the database to both application. My database is on localhost.
var MongoClient = require('mongodb').MongoClient;
var MONGO_HOSTS = {
undefined: 'localhost:27017',
'development': 'localhost:27017',
'test': 'localhost:27017',
'staging': process.env.MONGO_HOST,
'production': process.env.MONGO_HOST
};
// Connection URL
var url = 'mongodb://' + (process.env.MONGO_HOST || MONGO_HOSTS[process.env.NODE_ENV]) + '/test' + process.env.NODE_ENV;
Then connect to the database. The problem is that when I insert in one application the other application don't find it. Is this valid way of connection or is there other way.
Communicating via database is not the best pattern. But if you would like to do that, make sure you're trying to read data from DB after write was successful. Try also finding that document using first DB to make sure that your 'find' query is working.