Change database connection depending on route in express.js with sequelize - javascript

Is it possible to change the database connection in sequelize depending on the route?
For example, Users have access to 2 different installations in a website:
- example.com/foo
- example.com/bar
Upon login users are redirected to example.com/foo
To get all their tasks for the foo site, they need to visit example.com/foo/tasks
The bar site uses a separate database and thus if they want to get all their tasks for bar they have to go to example.com/bar/tasks
Every installation has its own database, and all databases have the same schema.
Is it possible to change the database connection depending on which route is visited?
*login only occurs once

This is possible. There are a number of ways to do this. Here's how I might approach it.
Router.js
var router = express.Router()
// This assumes the database is always the 2nd param,
// otherwise you have to enumerate
router.use('/:database/*', function(req, res, next){
req.db = req.params.database;
next();
}
Connection.js
var fooDB = new Sequelize('postgres://user:pass#example.com:5432/foo');
var barDB = new Sequelize('postgres://user:pass#example.com:5432/bar');
module.exports = {
foo: fooDB,
bar: barDB,
}
Tasks.js
var connection = require('connection);
function getTasks(req, params){
var database = connection[req.db];
//database now contains the db you wish to access based on the route.
}
That said, there are some interesting problems you'll have to face when you want to duplicate the schema across both, but that's probably best for another question.
I hope this helps!

I think is better to change collections depending on the route.
Have foo_tasks collection and bar_tasks collection in the same database.
Or have the attribute type in the tasks collection that specifies if the task is a "foo task" or a "bar task".

Related

Logout All sessions for an account in express-session, postgresql (connect-pg-simple)

I was wondering how one would create a route to logout all sessions (not just the current one) for a user when using express-session and connect-pg-simple as a session store.
I have the sessions table name set as user_sessions and have previously been able to achieve this using the mysql store on a previous project, which went something like this;
const db = require("../db/connection");
exports.logoutAllDevices = async (user_id) => {
// req.logout(); -- I called this in the controller just before, left it here to show its been called
let logoutAllQuery = 'DELETE FROM user_sessions WHERE JSON_EXTRACT(`data`, "$.passport.user") = $1;';
await db.query(logoutAllQuery, [user_id]);
return;
};
which i found before and the idea was to destroy all sessions related to that user as well as calling the req.logout() function.
However, I can't get any solution to work with this postgres store. Help is appreciated.

Mongodb does not save a document

I am trying to store some data from an HTML formulary. I send the data using the HTTP POST method and I received them using Express framework in Node.js. The data arrives and it seems to work, but when I try to store them into MongoDB using Mongoose, the database is created but no data is stored when I execute DB.sis_dictionary.find()
I've tried to build different types of schemas and models, but none seems to work. And I get no error from Node.js, it seems to be working, but the MongoDB database does not store anything.
const Mongoose = require('mongoose');
Mongoose.connect('mongodb://localhost:27017/sis_dictionary', {useNewUrlParser: true});
const Schema = Mongoose.Schema;
const wordSchema = new Schema({
word: String
})
const Word = Mongoose.model('Word', wordSchema);
app.post('/saveWord', (req, res) => {
var word = new Word({word: String(req.body)});
word.save(function(err){
if(err) {
return console.error(err);
} else {
console.log("STATUS: WORKING");
}
})
console.log(req.body);
})
server.listen(3000);
console.log("SERVER STARTUP SUCCESS");
In the console, I get the message: "STATUS: WORKING".
sis_ditionary is your DB name and Words should be your collection name. As mongoose automatically creates a plural name for collection from a model if model name not specified when creating from a schema
db.collection.find() is a command to find a collection data when using mongo-shell. Run below command to get data:
use sis_dictionary
db.Words.find()
To beautify result use pretty method
db.Words.find().pretty()
First command will select DB and second command list collection data.
So when you execute db.sis_dictionary.find() it won't work because sis_dictinary is your DB name.
Nodejs way with 'mongoose'
//Model.find({});
Word.find({});
Also, check this line var word = new Word({word: String(req.body)});
What does req.body have? If req.body is {word:"example word"} then you directly pass req.body to modal constructor ie new Word(req.body);
According to your database URL, mongodb://localhost:27017/sis_dictionary, sis_dictionary is the database name.
And according to your mongoose model, Word is your collection name.
When you save a document, it saves under a collection. So you have to make a query under the collections.
So when you try to get data using DB.sis_dictionary.find(), definitely it won't work.
Your query should be like db.collection.find()
Use the following query,
use sis_dictionary
db.words.find()
// for better view
db.words.find().pretty()
For more please check the documentation.
Thank you everybody. You were all right, it was a problem related to my collections names. db.words.find().pretty() worked perfectly!The problem is solved.

Connecting Multiple database in the predefined Mongoose structure

First of all, I will give you a glimpse on our project:
We have an application, which has two user roles: Merchant and buyer.
A merchant signs up and stores his trade info in his account.
A buyer can also log into his own account and access his purchase info with that merchant. One buyer may deal with multiple merchants.
We are thinking of a mongo database structure where the universal mongo db has only two key value pairs:
merchant_id to database name. (Which merchant is assigned which db as each merchant should have separate db)
buyer_id to merchant ids. (say buyer Ram has relations with two merchants M01 and M02).
We want that when each merchant logs in, he should see only data from his db.
But when a buyer logs in, he should see data from the database of merchants with whom he has business relations. (Ram should see data pulled from the database of M01 and M02).
We want a separate database for each merchant who signs up on our portal. (Since each merchant has lots of transactions). We had defined all the functions such as calculations and all the logic part with the help of mongoose ORM. As we have defined a global db.js and then with the help of model, schema and routes we are using the mongoose connection request with the database.
Following are our problems:
When our server starts, it connects to the database that is defined in the db.js file and in that there is a connection request to a global database or we say a master database.
How can we connect more then one database, while remaining connected to the master database? (closing up the connection and connecting to a new database causes us to lose connectivity with the master database [Which has all our signup data] and hence is not a solution).
We want to make a new database for every merchant after that merchant signs up, based on some key (Like IDCardNo) a new separate database is created, and all the calculations and the logic part are being then defined dynamically which performs with that particular database.
One thing is that we have used mongo-client instead of mongoose to make a new database, but got stuck as we wanted to make all the master database calculations and logic part (that are being written earlier) to being dynamically operated. Our problem is: How can we define more than one database connection request to that db.js file, which is static in nature, and also all our logic and calculations part are being written on the basis of that mongoose connection and not as a separate function?
I just found a solution on the internet that makes different folders for each user having mongoose and also the node_modules folder separately, but we cannot do that here as there are so many connection requests which hinders the server performance and also the storage load will increase.
I found another solution: change mongoose to mongo-client. This solution is very expensive since it means that we have to redo many critical pieces of code-similar to making the product again.
I would request you to help us to solve this issue and architect this system.
You should be able to solve this issue with single document and latest MongoDB Stitch wherein we’ve field level access control .. i recommend you go thru Stitch capabilities once
You can connect to the multiple databases with the same models by:
var mongoose = require('mongoose')
var conn = mongoose.createConnection('mongodb://localhost/db1');
var conn2 = mongoose.createConnection('mongodb://localhost/db2');
var Schema = new mongoose.Schema({})
var model1 = conn.model('User', Schema);
var model2 = conn2.model('Item', Schema);
model1.find({}, function() {
console.log("this will print out last");
});
model2.find({}, function() {
console.log("this will print out first");
});
Maybe Instead of creating 2 separate databases for the merchant and buyer, you should define 2 mongoose schema or Collections one for the merchant, one for the buyer.
Merchant Schema
const mongoose = require('mongoose');
const schema = mongoose.Schema;
const merchantSchema = new schema({
// merchant details
})
mongoose.model('merchant',merchantSchema )
Buyer Schema
const mongoose = require('mongoose');
const schema = mongoose.Schema;
const buyerSchema = new schema({
// merchant will store merchant_id(merchant_id is unique id given
// by mongodb for every merchant you save in collection)
merchant: [{
type: schema.Types.ObjectId
ref: 'merchant'
}]
// buyer details
})
mongoose.model('buyer',buyerSchema)
As you mentioned, "merchant should see data only from his db(here collection)".
To show data to a particular merchant you can query merchant model.
Eg:
merchantSchema.findOne({_id: merchant_id})
And to show data to user of merchants with whom he has business relations you can use
buyerSchema.findOne({_id: user_id}).populate('merchant')
This will solve your problem I guess.

Is it safe to use a single Mongoose database from two files/processes?

I've been working on a server and a push notification daemon that will both run simultaneously and interact with the same database. The idea behind this is that if one goes down, the other will still function.
I normally use Swift but for this project I'm writing it in Node, using Mongoose as my database. I've created a helper class that I import in both my server.js file and my notifier.js file.
const Mongoose = require('mongoose');
const Device = require('./device'); // This is a Schema
var uri = 'mongodb://localhost/devices';
function Database() {
Mongoose.connect(uri, { useMongoClient: true }, function(err) {
console.log('connected: ' + err);
});
}
Database.prototype.findDevice = function(params, callback) {
Device.findOne(params, function(err, device) {
// etc...
});
};
module.exports = Database;
Then separately from both server.js and notifier.js I create objects and query the database:
const Database = require('./db');
const db = new Database();
db.findDevice(params, function(err, device) {
// Simplified, but I edit and save things back to the database via db
device.token = 'blah';
device.save();
});
Is this safe to do? When working with Swift (and Objective-C) I'm always concerned about making things thread safe. Is this a concern? Should I be worried about race conditions and modifying the same files at the same time?
Also, bonus question: How does Mongoose share a connection between files (or processes?). For example Mongoose.connection.readyState returns the same thing from different files.
The short answer is "safe enough."
The long answer has to do with understanding what sort of consistency guarantees your system needs, how you've configured MongoDB, and whether there's any sharding or replication going on.
For the latter, you'll want to read about atomicity and consistency and perhaps also peek at write concern.
A good way to answer these questions, even when you think you've figured it out, is to test scenarios: Hammer a duplicate of your system with fake data and events and see if what happen is OK or not.

node.js - how to switch a database in mongodb driver?

I'm new to this stuff and just stuck in the middle of nowhere. Am using node-mongodb-native and am in need to switch to another database (after authentication against admin db). I googled and found this topic where the creator of library recommends to keep a connection for each db in a hash. So my question is - how do I accomplish it?
Just create different database connections and store them in an object.
var dbConnections = {};
var dbConnections.authDb = new Db('adminDb', server, {});
dbConnections.authDb.authenticate(username, password);
var dbConnections.otherDb = new Db('otherDb', server, {});
Does that make sense?
There's an example hidden in the MongoDB driver docs under Db:
[...]
MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {
[...]
// Reference a different database sharing the same connections
// for the data transfer
var secondDb = db.db("integration_tests_2");
// Fetch the collections
var multipleColl1 = db.collection("multiple_db_instances");
var multipleColl2 = secondDb.collection("multiple_db_instances");
[...]
});

Categories