I am working on a rest api using nodejs, express and sequelize orm. The api i am creating is for a android application which is based on SAAS platform. Therefore, I need to create separate database for each user of my application. There will be a master database which will be used to identify the database credential for each user while logging in. The master database will be connected by default and in each api call, in each route i need to connect/create the user specific database including the tables.
/* This is my db.js file for master database connection using sequelize. */
require('dotenv').config();
const sequelize = require('sequelize');
module.exports = new sequelize('master_db', process.env.DB_USER, process.env.DB_PASS, {
host: process.env.DB_HOST,
dialect: 'mysql',
operatorAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
/* This is a model Demo.js */
const Sequelize = require('sequelize');
const db = require('../../db');
const Demo_table = db.define('demo_table', {
// attributes
demo_id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
demo_name: {
type: Sequelize.INTEGER,
allowNull: false,
}
}, {
// options
timestamps: false,
freezeTableName: true,
});
module.exports = Demo_table;
/* This demo_route.js file in route folder*/
"use strict";
require('dotenv').config();
const express = require('express');
const router = express.Router();
const checkAuth = require('../middleware/auth');
//load controllers
const DemoController = require('../controllers/demo_member');
router.post('/demo_activity', checkAuth, DemoController.demo_activity);
module.exports = router;
/* This is the controller file demo_member.js*/
const moment = require('moment-timezone');
const Sequelize = require('sequelize');
const nodemailer = require("nodemailer");
const Op = Sequelize.Op;
//load models
const Demo = require('../models/Demo');
exports.create_demo_team = (req, res) => {
/* here i need to create the database of the user who is calling this api if the database(with tables) is not created else need to connect with the existing user's database and perform CRUD*/
}
I am expecting with the solution which will fulfil my requirement at the earliest. where i can create database dynamically, then create table and connect with it to perform CRUD.
Related
Here is some sample code that outlines my issue. I'm trying to get express-session / connect-session-sequelize to work for a website with login functionalities.
However, when I try to call my POST request, I get the following error:
I can only assume it's trying to store session data onto my database, but cannot find a table. I can bypass this by going in and creating the table manually with all the columns it wants, but I'm wondering if there's an issue in my code preventing the package from working properly (or if this is how it's supposed to work.)
require('dotenv').config({ path: './config/.env' })
const express = require('express')
const session = require('express-session')
const mysql = require('mysql2')
const Sequelize = require('sequelize')
const path = require('path')
const SequelizeStore = require('connect-session-sequelize')(session.Store)
const app = express()
const PORT = 9999
app.use(express.json())
app.use(express.static(path.join(__dirname, 'public')))
// Allowing connection to database in Workbench
const db = new Sequelize('somedatabase', 'root', process.env.PASSWORD, {
host: 'localhost',
dialect: 'mysql'
})
db.authenticate()
.then(() => {
console.log('Connected...')
}).catch(error => {
console.log('Failed to connect...', error)
})
// Setting up session
app.use(session({
secret: 'shhh',
store: new SequelizeStore({
db: db
}),
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000000
}
}))
// Sample model
const User = db.define('user', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: Sequelize.STRING,
password: Sequelize.STRING
})
// Sample request
app.post('/api/create', async (req, res) => {
const newUser = {
username: john,
password: verysecurepassword
}
await User.create(newUser)
})
app.listen(PORT, () => {
console.log(`Listening on localhost:${PORT}...`)
})
In this code, you are using several packages: express-session, which manages the session itself but delegates how the session is saved to connect-session-sequelize.
So the problem is that connect-session-sequelize is trying to save session data in the database, but it cannot because there is no table for sessions.
As written in the documentation of this package (https://www.npmjs.com/package/connect-session-sequelize):
If you want SequelizeStore to create/sync the database table for you, you can call sync() against an instance of SequelizeStore along with options if needed.
So try creating the store, attaching it to the session manager, and then
initializing it (I did not test this code):
// Setting up session
var myStore = new SequelizeStore({
db: db
});
app.use(
session({
secret: "shhh",
store: myStore,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000000
}
})
);
myStore.sync();
This question already has answers here:
How to connect MySQL database to ReactJS app?
(2 answers)
MySQL with Node.js
(9 answers)
Closed 3 years ago.
I'm beginner for React JS. Therefore, I want to learning how can used together React JS, Node JS and MySQL. So, Please give me some advises and example. I try do solve this problem. please help me guys.
You can't add back-end activity using ReactJs.
In Nodejs is possible.
You can connect MySql using sequelize ORM in nodejs.
Sequelize ORM
Sequelize is a promise-based Node.js ORM for Postgres, MySQL, SQLite and Microsoft SQL Server. It has many solid features for transaction, relations, read replication and more.
Try this:
>npm install --save sequelize
>npm install --save mysql2
Setting up Sequelize MySQL connection
./app/config/env.js
const env = {
database: 'testdb',
username: 'root',
password: '12345',
host: 'localhost',
dialect: 'mysql',
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
};
module.exports = env;
./app/config/db.config.js
const env = require('./env.js');
const Sequelize = require('sequelize');
const sequelize = new Sequelize(env.database, env.username, env.password, {
host: env.host,
dialect: env.dialect,
operatorsAliases: false,
pool: {
max: env.max,
min: env.pool.min,
acquire: env.pool.acquire,
idle: env.pool.idle
}
});
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
//Models/tables
db.customers = require('../model/customer.model.js')(sequelize, Sequelize);
module.exports = db;
Create Sequelize model
module.exports = (sequelize, Sequelize) => {
const Customer = sequelize.define('customer', {
firstname: {
type: Sequelize.STRING
},
lastname: {
type: Sequelize.STRING
},
age: {
type: Sequelize.INTEGER
}
});
return Customer;
}
Route
./app/controller/customer.route.js
module.exports = function(app) {
const customers = require('../controller/customer.controller.js');
// Create a new Customer
app.post('/api/customers', customers.create);
// Retrieve all Customer
app.get('/api/customers', customers.findAll);
// Retrieve a single Customer by Id
app.get('/api/customers/:customerId', customers.findById);
// Update a Customer with Id
app.put('/api/customers/:customerId', customers.update);
// Delete a Customer with Id
app.delete('/api/customers/:customerId', customers.delete);
}
Controller
const db = require('../config/db.config.js');
const Customer = db.customers;
// Post a Customer
exports.create = (req, res) => {
// Save to MySQL database
Customer.create({
firstname: req.body.firstname,
lastname: req.body.lastname,
age: req.body.age
}).then(customer => {
// Send created customer to client
res.send(customer);
});
};
// FETCH all Customers
exports.findAll = (req, res) => {
Customer.findAll().then(customers => {
// Send all customers to Client
res.send(customers);
});
};
// Find a Customer by Id
exports.findById = (req, res) => {
Customer.findById(req.params.customerId).then(customer => {
res.send(customer);
})
};
// Update a Customer
exports.update = (req, res) => {
const id = req.params.customerId;
Customer.update( { firstname: req.body.firstname, lastname: req.body.lastname, age: req.body.age },
{ where: {id: req.params.customerId} }
).then(() => {
res.status(200).send("updated successfully a customer with id = " + id);
});
};
// Delete a Customer by Id
exports.delete = (req, res) => {
const id = req.params.customerId;
Customer.destroy({
where: { id: id }
}).then(() => {
res.status(200).send('deleted successfully a customer with id = ' + id);
});
};
Server.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json())
const db = require('./app/config/db.config.js');
// force: true will drop the table if it already exists
db.sequelize.sync({force: true}).then(() => {
console.log('Drop and Resync with { force: true }');
});
require('./app/route/customer.route.js')(app);
// Create a Server
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("App listening at http://%s:%s", host, port)
})
In app.js at the backend folder that is like server.js in the backend that you made add these code :
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user:'root',
password:'mysqljs123',//password of your mysql db
database:'react-sql-db'
});
I've been unable to find a documented way of connecting to multiple MySQL databases in Feathers.js using Sequelize. Is there a way to do this? My use case is to be able to insert and get rows of data into multiple DBs from the same action but the DBs won't necessarily be the same schema.
Thanks!
I made some local test and it is possible. You need to define 2 different sequelize clients.
If you are using the CLI generator and you set up a service based on sequelize you should have a connection string (my example is a mysql db):
a db connection string in the config/default.json
"mysql" : "mysql://user:password#localhost:3306/your_db"
a sequelize.js in the src root folder
In order to create a second sequelize client
create a new connection string in the config/default.json
"mysql2" : "mysql://user:password#localhost:3306/your_db_2"
create a copy of sequelize.js and name it sequelize2.js
const Sequelize = require('sequelize');
module.exports = function (app) {
const connectionString = app.get('mysql2');
const sequelize2 = new Sequelize(connectionString, {
dialect: 'mysql',
logging: false,
operatorsAliases: false,
define: {
freezeTableName: true
}
});
const oldSetup = app.setup;
app.set('sequelizeClient2', sequelize2);
app.setup = function (...args) {
const result = oldSetup.apply(this, args);
// Set up data relationships
const models = sequelize2.models;
Object.keys(models).forEach(name => {
if ('associate' in models[name]) {
models[name].associate(models);
}
});
// Sync to the database
sequelize2.sync();
return result;
};
};
add the new sequelize configuration to your app.js
const sequelize2 = require('./sequelize2');
app.configure(sequelize2);
Then in your model to a second db :
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
module.exports = function (app) {
//load the second client you defined above
const sequelizeClient = app.get('sequelizeClient2');
//to check if connect to a different db
console.log ( sequelizeClient )
//your model
const tbl = sequelizeClient.define('your_table', {
text: {
type: DataTypes.STRING,
allowNull: false
}
}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});
// eslint-disable-next-line no-unused-vars
tbl.associate = function (models) {
// Define associations here
// See http://docs.sequelizejs.com/en/latest/docs/associations/
};
return tbl;
};
In order to work you need 2 different services, each one working with a different db.
If you want to put or get with a single action you can create a before/after hook in one of the service and call inside the hook the second service.
For the get you need to add the result of the second service to your hook result
I am trying to create a mysql database connection for my node app and ran sequelize.authenticate().then(function(errors) { console.log(errors) }); to test if the connection worked. The response that is logged to my console is Executing (default): SELECT 1+1 AS result undefined The undefined portion makes me think that the connection either didn't work or that there isn't any database found. I can't seem to figure that out. I thought by creating a database through Sequel Pro and connecting to localhost via the Socket, I can use the same credentials for connecting with my Node app. Do I need to create a file within my app for the database and not use the Sequel Pro database?
Controller file (where the connection is created):
var Sequelize = require('sequelize');
var sequelize = new Sequelize('synotate', 'root', '', {
host:'localhost',
port:'3306',
dialect: 'mysql'
});
sequelize.authenticate().then(function(errors) { console.log(errors) });
var db = {}
db.Annotation = sequelize.import(__dirname + "/ann-model");
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
ann-model.js (where my table is being defined):
module.exports = function(sequelize, DataTypes) {
var Ann = sequelize.define('annotations', {
ann_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
ann_date: DataTypes.DATE,
}, {
freezeTableName: true
});
return Ann;
}
Try this one, Executing (default): SELECT 1+1 AS result means that everything okay
sequelize
.authenticate()
.then(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
});
But i didn't know where you get undefined
I am trying to build restful-apis in node js using restful-sequelize and express.
I am having two tables, Category and Product. I want my get url for Categories to return the Category with the list of products associated with it.
For e.g. /api/categories should return -
[{"category_id":1,"name":"kids", "products":[/*list of products*/]}]
How can I do that? Examples would be of great help.
I think maybe my relations are not defined correctly, or I need to modify the findAll() method.
My code is as follows:
var express = require('express')
, bodyParser = require('body-parser')
, Sequelize = require('sequelize')
, http = require('http')
, Restful = require('new-sequelize-restful')
, sequelize = new Sequelize('test', 'root', 'root', {
logging: console.log,
define: {
timestamps: false
}
})
, app = express();
var port = process.env.PORT || 3000;
app.use(bodyParser());
var Category = sequelize.define('categories', {
category_id: {type:Sequelize.INTEGER, primaryKey:true},
name: Sequelize.STRING
});
var Product = sequelize.define('products', {
product_id: {type:Sequelize.INTEGER, primaryKey:true},
name: Sequelize.STRING,
description: Sequelize.STRING,
price: Sequelize.FLOAT,
categoryCategoryId: Sequelize.INTEGER
});
// Relationship definition
Category.hasMany(Product, {as:'products'});
app.all(/\/api\//, (new Restful(sequelize)).route());
app.listen(port);
console.log('Magic happens on port ' + port);
Which I myself resolved as follows:
First fix assocation:
Category.hasMany(Product, {
as: 'products',
foreignKey: 'categoryCategoryId'});
Then:
Category.findAll({
include: [{
model: Product,
'as': 'products' //because you rename model Product on association with Category
}]}).then(function(response) {
console.log(response)}, function(err) {
console.log(err)});