Is there a way to use multiple databases with a single connection to mongodb? I've found this:
https://mongodb.github.io/node-mongodb-native/api-generated/mongoclient.html#open
but as best I can tell those docs are old as there does not appear to be an open method on the MongoClient? Do you actually need to establish multiple connections?
Thanks!
Found it:
http://mongodb.github.io/node-mongodb-native/2.0/api/Db.html#db
Here is their example
var MongoClient = require('mongodb').MongoClient,
test = require('assert');
MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {
test.equal(null, err);
// Reference a different database sharing the same connections
// for the data transfer
var secondDb = db.db("integration_tests_2");
...
It is synchronous. Seems strange to me this method doesn't have the word "use" in it. Also seems strange it belongs to the db class. db.db('other_db').. a bit obscure. Did some tests, seems to work, so I'll mark this as the answer for anyone else that ends up here.
Related
I have a Node.js project dealing with multiple customers. For several reasons, mainly separation of concerns, security, and partial transferability, I have to put every customer's data into a separate Mongo database. All databases store the same object types and thus have the same set of collections with identical structure. I have already found many technical solutions to solve that issue, but my question is more concerned with the best practices handling this situation. A simplified view into my code (omitting the boilerplate code to create a server, module structure, etc.):
const mongoose = require('mongoose');
// Customer codes act as DB names, actually comes from config file or DB
let customers = ['c1', 'c2'];
// keeps all mongoose connections
let conns = {};
// create a connection(pool) for each DB
for (let i in customers) {
let dbname = customers[i];
conns[dbname] = mongoose.createConnection(`mongodb://${host}:${port}/${dbname}`);
}
// a simple Schema for blog articles
const ArticleSchema = new mongoose.Schema({
title: String,
text: String
});
// keeps all Article models
let Article = {};
// create the identical models for the different DBs
// remember: the dbname is the unique customer's code
for (let dbname in conns) {
let conn = conns[dbname];
Article[dbname] = conn.model('Article', ArticleSchema);
}
const app = require('express');
// returns all articles of a certain customer
app.get('/customers/:customerid/articles', function(req, res) {
// get the customer's code from the URL
let dbname = req.params.customerid;
// Query the database
Article[dbname].find({}, function(err, articles) {
if (err) return res.status(500).send('DB error');
res.status(200).send(articles);
});
});
This code works. Nonetheless, I wonder, if there ist a best practice I am not aware of to handle this kind of requirement. Especially, it feels strange to keep the connections and models in maps and to access the objects with the dbname in square brackets. Please keep in mind that this is an extremely simplified version. In the real version the code is distributed across several modules handling different object types etc.
Note: A simple mongoose.connection.useDb(dbName) to switch to a different database doesn't work since the model has to be registered with respect to the connection, which itself must be bound to a database (as far as I understand it).
Update: Handling every customer with a single node process and setting up a proxy switching to those processes with respect to the customer - as suggested in the question mentioned by Paul - is currently not an option due to the administrative effort necessary to set things up in our current environment. We have to launch the service quickly right now.
In the module mongoskin when getting the database object mongoskin does this in a sync fashion, hence the code:
var db = mongoskin.db(url, {
native_parser: true
});
var myCollection = db.collection('myCollection');
I am curious, how do they achieve this? I've been looking at the mongoskin code I however do not fully understand it.
And here, you can see mongoskin simplifys it :
https://github.com/kissjs/node-mongoskin#dbcollection-callback origin vs. mongoskin
Anyone know how mongoskin turned async code into sync fashion?
They say it in the beginning of the readme:
We make some common use functions in promise mode, we call it SkinClass of a normal Class. And the API is almost same with official API.
db.collection('myCollection'); returns SkinCollection - a wrapper for native Collection, which will use Collection when it is available.
The magic lives here: https://github.com/kissjs/node-mongoskin/blob/master/lib/utils.js
I have a module for connecting to my DB and perform actions.
Then in my main script (app.js) I instantiate it like
var DBConn = require('./common/DBConn');
And from that script it works fine. But then I've got some other scripts that handle routes, and I want to perform some DB stuff on those, but if I use DBConn it returns an error saying "DBConn is not defined".
Then I can just instantiate another DBConn in these other js files, but this would mean I am creating a connection for each file, right? But I want these other scripts to use the DBConn object from the app.js, so that I'm not constantly establishing a connection to the DB and then closing it... (unless this is a good idea, but to me it makes more sense to have just one "global" object dealing with the connection over all the app and that's it).
(BTW: I'm using Express)
You want to require() your module in each file. Node will cache the module.
Typically, the context of a DB connection is abstracted away behind stores or repositories and your other modules interact with those. In cases where people are directly requiring modules like mongoose, they'll require mongoose everywhere but only call the connection code within their main application entry point (app.js/server.js/whatever).
https://nodejs.org/api/modules.html#modules_caching
Modules are cached after the first time they are loaded. This
means (among other things) that every call to require('foo') will get
exactly the same object returned, if it would resolve to the same
file.
Multiple calls to require('foo') may not cause the module code to be
executed multiple times. This is an important feature. With it,
"partially done" objects can be returned, thus allowing transitive
dependencies to be loaded even when they would cause cycles.
If you want to have a module execute code multiple times, then export
a function, and call that function.
You could use a singleton to solve this issue for you. Please remember however that singletons come with their own set of problems (a good discussuon on singletons can be found here What is so bad about singletons?).
That said once you take into consideration the pro's and cons of singletons they can be a fantastic solution to exactly this problem.
Example:
// database.js
var singleton = function singleton() {
this.DbConnection = {};
function setup(database, username, password) {
this.DbConnection = MakeDbConnection()
};
};
singleton.instance = null;
singleton.getInstance = function(){
if(this.instance === null){
this.instance = new singleton();
}
return this.instance;
};
module.exports = singleton.getInstance();
This can then be called elsewhere in your application like so...
// main.js
var db = require("./database");
db.setup('db', 'root', 'pass');
db.DbConnection();
Once you have called db.setup() the first time, the db connection will be available just with the following:
// elsewhere.js
var db = require("./database");
db.DbConnection();
im trying to use a global database object to handle the data on my nodejs server. It shall contain all data of all connected users. Ready to be accessed anytime out of ram.
Therefore i created a module:
function Database() {
var MongoClient = require('mongodb').MongoClient;
this.dbcon; //database connection
// Connect to the db
MongoClient.connect("mongodb://localhost:27017/dbname", this.givedatabasevars);
};
As i want to reuse the database connection instead of opening new ones everytime i want to access the propertys of my object using the callback function and give them the connection object:
Database.prototype.givedatabasevars = function(err, getdbcon) {
if(err) {console.log(err)};
this.dbcon = getdbcon; //not working(scoped changed when used as callback?)
db.dbcom = getdbcon; //also not working(db object maybe not there yet as its a callback in constructor?)
};
I create the object using this globaly:
var Database = require('./node_modules/database/database.js');
var db = new Database();
Now im pretty new to nodejs and javascript all together. I tryed to get my head around how to access the objects scope, but from within the callback i cant even access the global scope.
Is this even possible?
Its the same for what to do with the data when using .find() with a callback. How do i get the data out of there to be used by my application? I need to store it, not to use it directly.
Regards,
Michael
You can access the global object using the global variable. Do console.log(this) on a plain file to see all the globals.
And for mongodb maybe mafintosh/mongojs can give you a more shareable interface. In fact I think with that you don't even need to have a global necessarily ;)
I'm using Subsonic 3.0.0.3 Active Directory.
During program work, opens many connections to MySQL data base. I can see this threads in MySQL Administrator.
I'm working with data base in this case:
var db = new DB();
var nClient = Enumerable.First(db.clients, c => c.id_client == cl.ID);
nClient.data = data;
nClient.Update();
another example
var nClient = new client { data= cl.data };
nClient.Save();
How should I correctly close connection to database? Or how to use only one connection to database?
It will close the connection straight way. SubSonic was designed to only open the connection when needed and close when finished.
If you want to use the same connection for several queries you need to look in to the batch query