How to connect to multiple databases through Sequelize? - javascript

I need to connect to different databases depending on the Express route.
For example:
example.com/oneapp
This route must access a database called oneapp
example.com/secondapp
This route must access a database called secondapp
I have these settings in my Sequelize
index.js:
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const config = require('../../config/database.js');
const db = {};
const sequelize = new Sequelize(config.producao);
fs
.readdirSync(__dirname)
.filter(file => (file.indexOf('.') !== 0) && (file !== path.basename(__filename)) && (file.slice(-3) === '.js'))
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
console.log(db)
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
database.js
module.exports = {
"producao": {
username: 'sa',
password: 'mypass',
database: 'PRODUCAO',
host: 'SVRNAZ002',
dialect: 'mssql',
}
}

Run that code twice with different db settings and keep two sets of the sequelize connection object and array of models.
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const configs = [require('../../config/database.js'), require('../../config/database2.js')];
module.exports = configs.map(config => {
const db = {};
const sequelize = new Sequelize(config.producao);
// load stuff like normal
db.sequelize = sequelize;
db.Sequelize = Sequelize;
return db;
});
Now you can access both:
const models = require('index');
const firstdb = models[0];
const seconddb = models[1];

maybe this is not the right answer, but I use it and it works.
first I use it for databases usually, the second for images
db.js
const {Sequelize} = require('sequelize')
const config = [
{
dialect: 'sqlite',
storage: './db.sqlite'
},
{
dialect: 'sqlite',
storage: './db_gambar.sqlite'
}
]
const database = config.map( x => new Sequelize(x));
module.exports = { database }
./models/akun.js
const { DataTypes, Model } = require('sequelize');
const { database} = require('./../db');
const sequelize = database[0];
// Tambahan is extend Model
class Akun extends Tambahan{}
Akun.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
}
},{ sequelize, underscored: true})
./models/gambar.js
const { DataTypes, Model } = require('sequelize');
const { database } = require('./../db');
const sequelize = database[1];
// Tambahan is extend Model
class Gambar extends Tambahan{}
Gambar.init({
name: {
type: DataTypes,
allowNull: false
},
user_id: {
type:DataTypes.INTEGER,
allowNull: false
},
data: {
type:DataTypes.BLOB,
allowNull: false
},
thumbnail: {
type: DataTypes.BLOB,
allowNull: false
}
},{ sequelize , underscored: true})

Related

Cant export multiple Sequelize Models from single file

I have 3 sequelize models that i have defined imported into a file called sequelize.js like so:
const { Sequelize } = require("sequelize");
const UserModel = require("./models/user");
const ItemModel = require("./models/item");
const ReservationModel = require("./models/reservation");
const config = require("./dbconfig");
const db = config.database;
const Item = ItemModel(sequelize, Sequelize);
const User = UserModel(sequelize, Sequelize);
const Reservation = ReservationModel(sequelize, Sequelize);
Reservation.hasMany(Item);
Item.belongsTo(Reservation);
Reservation.belongsTo(User);
I then try to export them:
module.exports = { Item, User, Reservation };
However, when I try to access one of them and use a model function, I get an error.
const Model = require("../../sequelize");
const passport = require("passport");
module.exports = (app) => {
app.post("/registerUser", (req, res, next) => {
passport.authenticate("register", (err, user, info) => {
if (err) {
console.log(err);
}
if (info !== undefined) {
console.log(info.message);
res.send(info.message);
} else {
req.logIn(user, (err) => {
const data = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
username: user.email,
};
Model.User.findOne({
where: {
email: data.username,
},
}).then((user) => {
user
.update({
first_name: data.first_name,
last_name: data.last_name,
email: data.email,
})
.then(() => {
console.log("user created in db");
res.status(200).send({ message: "user created" });
});
});
});
}
})(req, res, next);
});
};
results in
TypeError: User.findOne is not a function
This is not an issue when I just export one of them.
module.exports = User;
const User = require("./sequelize");
...
User.findOne(...) //works
I've tried multiple ways of exporting, but none seem to work.
e.g
module.exports = {
Item: Item,
User: User,
Reservation: Reservation,
}
and
exports.Item = Item;
exports.User = User;
exports.Reservation = Reservation;
edit: Here is my user model for reference
module.exports = (sequelize, type) => {
return sequelize.define(
"user",
{
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
first_name: type.STRING,
last_name: type.STRING,
credentials: type.STRING,
email: {
type: type.STRING,
allowNull: false,
},
password: {
type: type.STRING,
allowNull: false,
},
},
{
tableName: "Users",
}
);
};
Why cant I export these multiple objects?
I have the exact structure you're using by importing all sequelize models into one file then module.exporting them in an object and the only thing I see thats different is how you define your models. I might be out of date but I learned as such:
const Sequelize = require('sequelize');
const db = require('../db');
module.exports = db.define('users', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
unique: true
},
}, {
timestamps: true,
});
Db declaration
const Sequelize = require('sequelize');
const db = new Sequelize(
process.env.DATABASE_URL, {
logging: false
}
);
module.exports = db;
Then your central import
const User = require('./user');
const Order = require('./order');
Order.belongsTo(User)
User.hasMany(Order)
module.exports = {
User,
Order
};
Then using it
const models = require('./models');
const results = await models.User.destroy({
where: {
id: id
}
});
if(results){
return results;
}
Found what was wrong. In my passport.js file, where I defined my localStrategy, I was doing an incorrect import.
My export in sequelize.js was
modules.export = {Item, User, Reservation};
while my import in passport.js was just
const User = require("../sequelize");
when it should have been
const Model = require("../sequelize");
const User = Model.User;
looks like I had it imported correctly in my signUp route, but not in my passport config file!

Cannot read property 'findOrCreate' of undefined with sequelize-auto

I'm not really good at English and coding something. My OS is Mac and here is my basic info
dialect : mysql
sequelize-ver: 6.3.3
folder structure
I wrote my problem in the below on my question.
First, I imported .sql file to my database and i made models automatically from sequelize-auto, and also migrated automatically from sequelize-auto-migrate. ( I really appreciate about it. )
Here is my Mentors model ( I made signUp controller from this model. )
/* jshint indent: 2 */
// eslint-disable-next-line no-unused-vars
const { Model } = require('sequelize');
module.exports = function (sequelize, DataTypes) {
return sequelize.define('Mentors', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
mentor_name: {
type: DataTypes.STRING(255),
allowNull: true,
},
nickname: {
type: DataTypes.STRING(255),
allowNull: true,
},
email: {
type: DataTypes.STRING(255),
allowNull: true,
},
password: {
type: DataTypes.STRING(255),
allowNull: true,
},
sex: {
type: DataTypes.STRING(255),
allowNull: true,
},
phone: {
type: DataTypes.STRING(255),
allowNull: true,
},
birthday: {
type: DataTypes.STRING(255),
allowNull: true,
},
certification_path: {
type: DataTypes.STRING(255),
allowNull: true,
},
intro: {
type: DataTypes.STRING(255),
allowNull: true,
},
created_at: {
type: DataTypes.DATE,
allowNull: true,
},
}, {
sequelize,
tableName: 'Mentors',
});
};
and here is my model index.js
/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
// 'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development'; // 환경변수 NODE_ENV를 설정 안 해줄 경우 test 객체 연결 정보로 DB 연결 설정
const config = require(__dirname, +'/../config/config.js')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter((file) => ((file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')))
.forEach((file) => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
and last, here is my signUp controller
const { Mentors } = require('../../models/Mentors');
module.exports = {
post: (req, res) => {
const {
// eslint-disable-next-line camelcase
mentor_name, nickname, email, password, sex, phone, birthday, certification_path, intro,
} = req.body;
Mentors
.findOrCreate({
where: {
email,
},
defaults: {
mentor_name,
nickname,
password,
sex,
phone,
birthday,
certification_path,
intro,
},
})
// eslint-disable-next-line consistent-return
.then(async ([result, created]) => {
if (!created) {
return res.status(409).send('Already exists user');
}
const data = await result.get({ plain: true });
res.status(200).json(data);
}).catch((err) => {
res.status(500).send(err);
});
// console.log('/mentor/signup');
},
};
and now, I'm facing this error when I type 'npm start'
TypeError: Cannot read property 'findOrCreate' of undefined
error screenshot
I googled a lot because of this problem, but still can't find out solution...
please help me how to solve this problem.
here is my config.js
development: { // 배포할 때 RDS 연결 정보
username: 'root',
password: '(something)',
database: 'user',
host: 'localhost',
port: 3001,
dialect: 'mysql',
logging: false,
},
};
here is my app.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const port = 3001;
// routes
const mentorRouter = require('./routes/mentor');
// const menteeRouter = require('./routes/mentee');
/*
* bodyparser.json() - body로 넘어온 데이터를 JSON 객체로 변환
*/
app.use(bodyParser.json());
/*
* bodyParser.urlencoded({ extended }) - 중첩 객체를 허용할지 말지를 결정하는 옵션
* 참고 링크(https://stackoverflow.com/questions/29960764/what-does-extended-mean-in-express-4-0/45690436#45690436)
*/
app.use(bodyParser.urlencoded({ extended: false }));
/*
* cors() - CORS를 대응하기 위한 라이브러리 ( Access-Control-Allow-Origin: * )
* https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
*/
app.use(
cors({
origin: ['http://localhost:3000'],
methods: ['GET', 'POST', 'PATCH'],
credentials: true,
}),
);
app.use('/mentor', mentorRouter);
// app.use('/mentee', menteeRouter);
app.set('port', port);
app.listen(app.get('port'), () => {
console.log(`app is listening in PORT ${app.get('port')}`);
});
// 나중 테스트 코드에서 쓰기 위해 export
module.exports = app;
change your import statement in controller to import model index file like this
const db = require('../../models');
and then use it like
db.Mentors.findOrCreate()

Sequelize.js/Node.js/Express.js: Tasks.findAll()returns a TypeError:Cannot read property 'findAll' of undefined

code is supposed to return a a JSON object with empty tasks when requesting /tasks instead it returns a message error- TypeError: cannot read property 'findAll' of undefined. The source of errors as per the message comes from routes >tasks.js see below for screenshots or/and live code on sandbox.
Project Folder:
sandbox
some codes:
src>models >tasks.js
module.exports = (sequelize, DataType) => {
const Tasks = sequelize.define(
"Tasks",
{
id: {
type: DataType.INTEGER,
primaryKey: true,
autoIncrement: true
},
title: {
type: DataType.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
done: {
type: DataType.BOOLEAN,
allowNull: false,
defaultValue: false
}
},
{
classMethods: {
associate: models => {
Tasks.belongsTo(models.Users);
}
}
}
);
return Tasks;
};
src>routes>tasks.js
module.exports = app => {
const Tasks = app.db.models.tasks;
app.get("/tasks", (req, res) => {
Tasks.findAll({}).then(tasks => {//source of error as per error message
res.json({ tasks: tasks });
});
});
};
src >db.js
var path = require("path");
var fs = require("fs");
var Sequelize = require("sequelize");
//const config = require("./libs/config.js");
var sequelize = null;
let db = null;
module.exports = app => {
if (!db) {
const config = app.libs.config;
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config.params
);
db = {
sequelize,
Sequelize,
models: {}
};
const dir = path.join(__dirname, "models");
fs.readdirSync(dir).forEach(file => {
const modelDir = path.join(dir, file);
const model = sequelize.import(modelDir);
db.models[model.name] = model;
});
Object.keys(db.models).forEach(key => {
db.models[key].options.classMethods.associate(db.models);
});
}
return db;
};
src>index.js
var express = require("express");
var consign = require("consign");
var app = express();
consign({ cwd: "src" })
.include("./libs/config.js")
.then("db.js")
.then("./libs")
.then("./routes")
.into(app);
On file routes/tasks.js line 2, add a capital on task;
const Tasks = app.db.models.Tasks;
Then it should works.

My Sequelize/Node setup wrong? Am I doing something obviously wrong?

I'm building a project with Express, trying to use the Sequelize ORM to access a mySQL database.
The errors I'm getting waver between not having models defined and findAll of Orders being a function and not an object I can query.
Is there an obvious flaw in my setup? Thanks!
Order.js:The Model
'use strict';
module.exports = (sequelize, DataTypes) => {
var Order = sequelize.define('stores', {
index: DataTypes.INTEGER,
server: DataTypes.STRING,
gridName: DataTypes.STRING,
x: DataTypes.INTEGER,
y: DataTypes.INTEGER,
z: DataTypes.INTEGER,
owner: DataTypes.STRING,
item: DataTypes.STRING,
deal: DataTypes.STRING,
quantity: DataTypes.INTEGER,
price: DataTypes.INTEGER,
GPS: DataTypes.STRING
});
return Order;
};
index.js:The model aggregator
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
// const config = require(__dirname + '/..database.json')[env];
const db = {};
let sequelize;
// if (config.use_env_variable) {
// sequelize = new Sequelize(process.env[config.use_env_variable]);
// } else {
sequelize = new Sequelize('db', 'user', 'pw', {
host: 'ip',
dialect: 'mysql2'
});
// }
fs
.readdirSync(__dirname)
.filter(function(file) {
return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js';
})
.forEach(function(file) {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
marketRoutes.js:The query controller
const models = require('../models');
module.exports = (app) => {
app.get('/api/requestOrders', (req, res) => {
console.log('hitting route', models.Order);
models.Order
.findAll()
.then(function(orders) {
console.log(orders);
})
.catch(function(err) {
console.log(err);
});
});
};
I think marketRoutes.js is looking for models in the wrong place. Shouldn't you be require index.js, so you can access the models imported from the file system and stored in the db object?
(I use a models directory... but there are some advantages to using sequelize.import)

Best way to import sequelize models in node.js

I am using sequelize orm in node.js. I have made models folders for all model like userModel.js, in userModel.js I have some class-based functions like login and getToken.
// some code of userModel.js
const jwt = require('jsonwebtoken');
module.exports = (sequelize, Sequelize) => {
const UserSchema = sequelize.define('User', {
first_name: {
type: Sequelize.STRING,
},
last_name: {
type: Sequelize.STRING,
},
});
// generate token
UserSchema.genToken = (id) => {
return jwt.sign({ id }, 'test');
}
// user login
UserSchema.login = function (body) {
const User = this;
return User.findOne({
where: { email: body.email}
})
.then((result) => {
return result;
})
.catch((err) => {
return Promise.reject(err);
})
}
return UserSchema;
}
when i import userModel.js in db.js
const Sequelize = require('sequelize');
const config = {};
var db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: config.dialect,
operatorsAliases: false,
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = sequelize.import('./../models/userModel');
module.exports = db;
so my question is when I using db variable for userModel like
db.User
I am using VS code editor for coding. So now VS code is showing me all suggestion of sequelize models but it is not showing my functions for login and genToken
//suggest
db.User.find()
db.User.findOne()
//but not include these
db.User.login()
db.User.genToken()
Even when I use db.User.login() or db.User.genToken() it's working as I want but right now I will have to open userModel.js again and again for seeing the name of all functions. How can I import models in a better way?

Categories

Resources