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()
Related
Good evening I'm getting this error in my express JS application and not sure how to resolve it.
I'm using an existing mySQL db and trying to retrieve items from my tbl_person table in myDB database. I'm pretty new to this, I'm not too sure what I'm doing incorrect. Some of the examples I'm seeing online is not entirely clear so I need some help.
Here is my sample code:
db.config.js
module.exports = {
HOST: "127.0.0.1",
USER: "root",
PASSWORD: "password",
DB: "myDB"
};
person.model.js
module.exports = (sequelize, DataTypes) => {
const Person = sequelize.define('tbl_person', {
personID: {
type: DataTypes.STRING(36),
field: 'personId',
allowNull: false,
primaryKey: true,
},
accountname: {
type: DataTypes.STRING(50),
field: 'accountname',
allowNull: true,
},
password: {
type: DataTypes.STRING(100),
field: 'password',
allowNull: true,
},
nameprefix: {
type: DataTypes.STRING(20),
field: 'nameprefix',
allowNull: true,
},
firstname: {
type: DataTypes.STRING(50),
field: 'firstname',
allowNull: true,
},
middlename: {
type: DataTypes.STRING(50),
field: 'middlename',
allowNull: true,
},
lastname: {
type: DataTypes.STRING(50),
field: 'lastname',
allowNull: true,
},
})
return Person;
};
person.controller.js
const person = require("../models/person.model.js").Person;
module.exports = {
getPersons(req, res) {
person.findAll({
where: { isActive : 1 },
}).then(person => {
res.status(201).json({
person: person,
success: true,
message: "get person request successful."
});
}).catch(error => {
console.error("get person request failed: ", error);
res.status(500).send({
success: false,
message: "get person request failed: " + error
});
})
}
};
index.js
const person = require("../controllers/person.controller.js");
module.exports = app => {
app.get("/api", (req, res) =>
res.status(200).send({
message: "Welcome to my API!",
})
);
// ========================= Person Routes ========================= //
app.get("/api/person/get", person.getPersons);
};
server.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
require("./routes/index.js")(app);
app.get("*", (req, res) => {
res.status(404).send({
status: false,
message: "No matching route!"
});
});
//PORTS
const port = process.env.PORT || 3000;
// set port, listen for requests
app.listen(port, () => {
console.log(`Server is running on port ${port}.`);
});
You should register all models and their associations before using them. And you should use them either from Sequelize instance or from your object holding all registered models.
See my answer here about how to register all models and associations.
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.
I am learning how to use Sequelize ORM in Nodejs and save data in Postgres Database.
My goal is to insert user data into Users table. I have created the table using migration, and it works. However, I am not able to save users data. I 've followed many resources for example Tut 1 Tut 2, etc.. , I still get the same error
C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\database\models\index.js:12
if (config.use_env_variable) {
^
TypeError: Cannot read property 'use_env_variable' of undefined
at Object.<anonymous> (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\database\models\index.js:12:12)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at babelWatchLoader (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:51:13)
at Object.require.extensions.(anonymous function) [as .js] (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:62:7)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Module.require (internal/modules/cjs/loader.js:690:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (C:\Users\HP\Desktop\Andela\project\Tutorials\react-project\chat_app_api\server\server.js:1:1)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at babelWatchLoader (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:51:13)
at Object.require.extensions.(anonymous function) [as .js] (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:62:7)
config/config.js
require('dotenv').config();
module.exports = {
development: {
use_env_variable: 'DATABASE_URL_DEV',
dialect: 'postgres',
},
test: {
use_env_variable: 'DATABASE_URL_TEST',
dialect: 'postgres',
},
production: {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
ssl: true,
dialectOptions: {
ssl: true,
},
},
};
migrations/20190927083519-create-user.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
},
fullname: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
username: {
type: Sequelize.STRING
},
telephone: {
type: Sequelize.STRING
},
image: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
models/index.js
'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';
const config = require(__dirname + '/../config/config.js')[env]; // why this return Undefined ?
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 => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
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;
models/users
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
fullname: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
username: DataTypes.STRING,
telephone: DataTypes.STRING,
image: DataTypes.STRING
}, {});
User.associate = function (models) {
// associations can be defined here
};
return User;
};
app.js
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import bodyParser from 'body-parser';
import { errors } from 'celebrate';
import routes from './Routes/index';
const app = express();
app.use(cors());
app.use(morgan('combined'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', routes);
app.use(errors());
app.use((req, res) => {
const error = new Error('Route not found');
error.status = 404;
return res.status(error.status).json({
status: error.status,
message: error.message,
});
});
// Server Error
app.use((error, req, res) => {
const status = error.status || 500;
return res.status(status).json({
status,
message: error.message || 'Server error',
});
});
export default app;
.env
DATABASE_URL_DEV=postgres://postgres:.#localhost:5432/db_dev
DATABASE_URL_TEST=postgres://postgres:.#localhost:5432/db_test
DATABASE_URL=postgres://user:password#host:5432/db_remote
controllers/userControllers.js
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
import models from '../../database/models';
import uploadImage from '../Helpers/upload.Image';
dotenv.config();
class UserController {
static async signup(req, res) {
const { body: input } = req;
input.password = bcrypt.hashSync(input.password, 10);
try {
const image = await uploadImage(req, res);
const { secure_url: img } = await image;
input.image = img;
console.log('result before ########################', models.User); // Undefined
const result = await models.User.create(input);
console.log('result after ########################', result); // Error here
delete result.dataValues.password;
const token = jwt.sign(result.dataValues, process.env.SECRET_KEY, { expiresIn: '1W' });
result.dataValues.token = token;
const status = 201;
return res.status(status).json({
status,
message: 'User successfully created',
data: result.dataValues,
});
} catch (error) {
console.log('error########################', error);
let { message } = error.errors[0];
const status = 500;
message = message || 'Server error';
return res.status(status).json({
status,
message,
});
}
}
}
export default UserController;
I still don't know why in models/index.js my config variable return undefined.
require(__dirname + '/../config/config.js') // return object
env // return environment
const config = require(__dirname + '/../config/config.js')[env]; //return Undefined
I spent 3 days debugging but I can not solve the Error. any help, guidance is highly appreciated.
Thanks
Guyz, I found an answer to my problem,
in models/index.js
I change process.env.NODE_ENV to process.env.NODE_ENV.trim()
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
// Before
const env = process.env.NODE_ENV || 'development';
// After
const env = process.env.NODE_ENV.trim() || 'development'; // add .trim()
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);
}
...
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Further Details
package.json
"scripts": {
"db:migrate:dev": "sequelize db:migrate --env development",
"db:migrate:test": "sequelize db:migrate --env test",
"db:migrate:production": "sequelize db:migrate --env production",
"db:reset": "sequelize db:migrate:undo",
"start": "SET NODE_ENV=production && babel-watch server/server.js",
"dev": "SET NODE_ENV=development && babel-watch server/server.js",
"test": "SET NODE_ENV=testing && babel-watch server/server.js"
}
Example, Let's say if I start the server by typing in the terminal
npm run dev
If i do console.log(process.env.NODE_ENV) // output is "development " with a space.
Hence,
process.env.NODE_ENV === "development" // return false
or
"development " === "development" // return false
Javascript Trim() remove whitespace from both sides of a string
You want more resource? please visit w3c
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})
I have the following two files running on an Express Node.js server:
home.js
var express = require('express')
var sequelize = require('sequelize')
var db = require('../../shared/db.js')
var op = sequelize.Op
var router = express.Router()
router.get('/home', function(req, res, next) {
db.shared.person.findAll({
where: {
email: {
[op.ne]: null
}
},
order: ['id']
}).then(function (person) {
res.locals = {
person: person
}
res.render('home')
})
})
module.exports = router
db.js
var sequelize = require('sequelize')
var config = {
host: 'localhost',
port: 5432,
username: '...',
password: '...',
database: 'postgres',
dialect: 'postgres',
operatorsAliases: false
}
var db = new sequelize(config)
module.exports = {
shared: {
person: db.define('person', {
id: {
type: sequelize.INTEGER,
primaryKey: true
},
name: sequelize.STRING,
email: sequelize.INTEGER
}, { freezeTableName: true , timestamps: false, schema: 'shared' }),
}
}
When I try to run this query, I get an error claiming Unhandled rejection Error: Invalid value { [Symbol(ne)]: null }
What am I doing wrong? I can use $ne and even ne just fine but they've been deprecated and are not entirely safe to use. Furthermore, it's not just [op.ne] - I get this error when I use any conditional like this.
I'm basing this all on this guide so I'm not really sure what I could be doing wrong here.
Unhandled rejection Error: Invalid value might also appear if you didn't setup string aliases like this:
const Op = Sequelize.Op;
const operatorsAliases = {
$eq: Op.eq,
$ne: Op.ne,
...
$any: Op.any,
$all: Op.all,
$values: Op.values,
$col: Op.col
};
const connection = new Sequelize(db, user, pass, { operatorsAliases });
But, better to remove String based aliases from code and use [Op.ne] for example, Sequlize is planning to deprecate them soon.
Sequelize instance in both db.js and home.js are different, this is because node caches a required module based on it path.
To solve this issue you can pass around correct instance in db.js
module.exports = {
shared: {
person: db.define('person', {
id: {
type: sequelize.INTEGER,
primaryKey: true
},
name: sequelize.STRING,
email: sequelize.INTEGER
}, { freezeTableName: true , timestamps: false, schema: 'shared' }),
},
db: db
}
Then finally use operators from that shared instance to do query
var express = require('express')
var sequelize = require('sequelize')
var db = require('../../shared/db.js')
var op = db.db.Op;
var router = express.Router()
router.get('/home', function(req, res, next) {
db.shared.person.findAll({
where: {
email: {
[op.ne]: null
}
},
order: ['id']
}).then(function (person) {
res.locals = {
person: person
}
res.render('home')
})
})
module.exports = router
One more thing, string operators are completely safe to use if you properly sanitize your user inputs. You only need to use secure operators if you are passing un-sanitized user input to Sequelize methods.
More on this topic
http://docs.sequelizejs.com/manual/tutorial/querying.html#operators-security
https://github.com/sequelize/sequelize/issues/8417