Connecting Multiple database in the predefined Mongoose structure - javascript

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.

Related

How to get all the data from tables using TypeORM?

I'm building a Nest.js app with PostgresQL using TypeORM, I have entity User and entity Role, which are connected to each other with Many-to-Many relation. User has an array of roles, where each role assigned to this user is stored, but when I try to get all the users, that roles array doesn't show. Using Sequelize ORM i could get all the data from users using that
code - {include: {all: true}}, example:
const users = await this.usersRepository.find({include: {all: true}})
But in TypeORM it doesn't work. I tried to find it in TypeORM docs, but I didn't find an answer.
Sorry for my english, i hope you understood me.
It seems TypeORM wait for a list of relations you want to populate : https://orkhan.gitbook.io/typeorm/docs/relational-query-builder
In your case, it could look like :
const users = await this.usersRepository.find({relations: {roles: true}})

postgres: relation does not exist when the table clearly exists when calling from node.js

so I psql'd and created table users;
CREATE TABLE users (
id integer NOT NULL,
username text
);
I am able to grab rows by doing SELECT * FROM users;
However, when I use node.js with the library module pg to make calls I get the infamous relation does not exist.
const createQuery = {text: "INSERT INTO users(id, username) VALUES($1)",values: values}
const { rows } = await db.query(createQuery);
I wasn't running into this issue before a complete server migration.
The most likely option is that the table was created in a different schema than the default schema that you are using from node.js.
You can search the schema your table belongs to by querying table information_schema.tables:
select table_schema from information_schema.tables where table_name = 'users';
With this information at hand, you can now qualify your table name with the proper schema name in the query that you are running from node.js. Assuming that the schema name is myschema, you would go:
INSERT INTO myschema.users(id, username) VALUES($1)
By default when you don't specify any schema, postgres points out to public schema. Please use schema name/ database name as along with the table name. Make sure you have provided proper configurations of the database within your code. If the configurations are proper and even you no need to provided schema alias within the query.

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.

Relationship with two APIs (nodejs, angular, express, mysql)

I am a beginner in angular / node and I have a question that maybe can be simple (I believe) ...
I was following the "Tour of Heroes" tutorial and started to wonder if it would be possible to have a type of "Contract"
Contract would receive the data of the api Hero (id, name ...) and also data of another api "Company" (id, name, location ...) and then join everything in a called api "Contract".
Then in that case I could list "Contract ID" or "contract number", and see the information (which company, which hero, that kind of thing)
Is it possible to do this with node, angular and mysql? if it is ... Could you show me some example or tutorial to follow?
Thank you!
That is possible and easy, you just need a few things set up:
Your db needs a contract table (assuming you want a many to many relationship between heroes and companies) where you set foreign keys to the hero_id and the company_id.
You need a new endpoint in your server that receives the contractId as a parameter and then you can do a request to your mysql db that uses your contract table to join the company to the hero, i.e.
SELECT * FROM hero AS h
JOIN contract AS cont ON h.id = cont.hero_id
JOIN company AS comp ON comp.id = cont.company_id
WHERE cont.id = ? ;
(replace the ? with the contract id you receive from the endpoint, ideally using prepared statements for mysql or a similar solution like the one mysqljs provides)
Angular will just need to call the new endpoint with a contractId parameter and you should receive the data if it exists.

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

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".

Categories