sequelize .create is not a function error - node.js

I'm getting Unhandled rejection TypeError: feed.create is not a function error and I can't understand why it occurs. What's the problem here?
Here's my code. I'm probably not doing something very fundamental here since I can't reach feed variable in routes/index.js.
If I add module.exports = feed; to my models file, I can reach it, but I have more than one models, so if I add additional models below the feed, they override it.
db.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize('mydatabase', 'root', 'root', {
host: 'localhost',
dialect: 'mysql',
port: 8889,
pool: {
max: 5,
min: 0,
idle: 10000
},
define: {
timestamps: false
}
});
var db = {};
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
models.js
var db = require('./db'),
sequelize = db.sequelize,
Sequelize = db.Sequelize;
var feed = sequelize.define('feeds', {
subscriber_id: Sequelize.INTEGER,
activity_id: Sequelize.INTEGER
},
{
tableName: 'feeds',
freezeTableName: true
});
routes/index.js
var express = require('express');
var router = express.Router();
var models = require('../models');
router.get('/addfeed', function(req,res) {
sequelize.sync().then(function () {
return feed.create({
subscriber_id: 5008,
activity_id : 116
});
}).then(function (jane) {
res.sendStatus(jane);
});
});

You cannot reach a variable from a file, by only requiring it in another one. You need to either define an object literal to hold all your variables in one place and assign it to module.exports, or you need to import them from different files separately.
In your case, I would create separate files to hold table schemas, and then import them by sequelize.import under one file, then require that file.
Like this:
models/index.js:
var sequelize = new Sequelize('DBNAME', 'root', 'root', {
host: "localhost",
dialect: 'sqlite',
pool:{
max: 5,
min: 0,
idle: 10000
},
storage: "SOME_DB_PATH"
});
// load models
var models = [
'Users',
];
models.forEach(function(model) {
module.exports[model] = sequelize.import(__dirname + '/' + model);
});
models/Users.js
var Sequelize = require("sequelize");
module.exports=function(sequelize, DataTypes){
return Users = sequelize.define("Users", {
id: {
type: DataTypes.INTEGER,
field: "id",
autoIncrement: !0,
primaryKey: !0
},
firstName: {
type: DataTypes.STRING,
field: "first_name"
},
lastName: {
type: DataTypes.STRING,
field: "last_name"
},
}, {
freezeTableName: true, // Model tableName will be the same as the model name
classMethods:{
}
},
instanceMethods:{
}
}
});
};
Then import each model like this:
var Users = require("MODELS_FOLDER_PATH").Users;
Hope this helps.

Just use
const { User } = require("../models");

Update :
in newer version of sequelize v6 and beyond sequelize.import is deprecated
sequelize docs recommend using require now
If you have generated models using migrations
this is how your model file will look like
models/user.js
'use strict'
module.exports = (sequelize, DataTypes, Model) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
};
User.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
phone_number: {
type: DataTypes.STRING(20)
},
otp: {
type: DataTypes.INTEGER(4).UNSIGNED
},{
sequelize,
modelName: 'User',
});
return User;
};
as you can see your model export function has sequelize DataTypes & Model parameters.
so when you import this model you should send above arguments.
Example
I am importing user model in controllers/user.js file, it could be any file
controllers/controller.js
const Sequelize = require('sequelize');
const sequelize = require('../config/db').sequelize;
// Bring in Model
const User = require('../models/user')(sequelize, Sequelize.DataTypes,
Sequelize.Model);
// your code...
// User.create(), User.find() whatever
Notice that sequelize(with small 's') and Sequelize(with capital 'S') are different things, first one represent instance of Sequelize created using new Sequelize, second one is just package you installed & imported
first one (sequelize) can be found wherever you started a connection to database using const sequelize = new Sequelize() usually from app.js or db.js file, make sure to export it from there and import it into where you want to use Model i.e controller
export sequelize instance
db.js Or app.js
const sequelize = new Sequelize();
... //your code
...
module.exports = {
sequelize: sequelize
}

You may want to check the answer given on the link below tackling the same issue, I was able to resolve mine using const User = sequelize.import('../models/users');, instead of just import User from '../models/users';
Sequelize create not a function?

I came with the same issue when I used something like:
const { Feed } = require("../models/Feed.js");
So, just using the code down below solved it
const { Feed } = require("../models");

Related

Cannot read property 'create' of undefined in expressjs

Please am new to Nodejs but am trying to insert a data into my database using sequelize but am getting Cannot read property .create of undefined.
This is my index.js file
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.DB,
config.USER,
config.PASSWORD,
{
host: config.HOST,
dialect: config.dialect,
operatorsAliases: false,
pool: {
max: config.pool.max,
min: config.pool.min,
acquire: config.pool.acquire,
idle: config.pool.idle
}
});
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
// db[model] = model
db.User = model
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db;
This is my Model/User.js File
module.exports = (sequelize, DataTypes) => {
sequelize.define('User', {
hmtec_email: {
type: DataTypes.STRING,
unique: true
},
hmtec_password: DataTypes.STRING
})
This is my Controllers/AuthController.js File
const {User} = require ('../models/User')
module.exports = {
async register (req, res) {
try {
const user = await User.create(req.body)
res.send(user.toJSON())
} catch (err) {
console.log(err);
res.status(400).send({
error: 'Email already in Use'
})
}
}
I don't know what wrong with the code, I dont know why am getting that error of .create is undefined
I think your problem is in the last file .. AuthController.js
const {User} = require ('../models/User')
You are using the Es6 new destruction assignment
More Info here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Normally you should define your variable without the brackets
That mean you got all of the variable available.
But adding the brackets means that you want to get the child of the object, this child is named user .. and then name the variable also as user
and search these info
From the require file after the equal.
But in your user file .. you are exporting a function .. that does not have any child named user
Thus undefined
Better alternative is to use Classes
More info here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
So in user model
// Inside your function you need to use sequalize module , iam not familar with it but you must require it to use it
const Sequelize = require('sequelize');
// Define the Class
class user {
// add the name you want to use for the function - here I used create so the other code also work - also I inserted async because this is asynchronous and also I removed the sequalize from parameters because you don't need it now after it is required above.
async create (DataTypes) => {
await Sequelize.define('User', {
hmtec_email: {
type: DataTypes.STRING,
unique: true
},
hmtec_password: DataTypes.STRING
})
}
module.exports = user;
Now when you require the file in Authcontroller , remove the brackets
const User = require ('../models/User')
and now you can use User.create(YOUR_DATA_VARIABLE);in your authController.js
and if there is any other functions inside this class you also can use them in the same manner.
I hope this fix your problem.

Sequelize OP -> TypeError: Cannot read property 'like' of undefined

In my project, i'd like to search many subways have a certain keyword.
So, I use Op in Sequelize, but it returned TypeError: Cannot read property 'like' of undefined.
The way I initialized the sequelize object is as follows.
// root/models/index.js
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
module.exports = db;
And, I initialized and used the Op object like this
const { Subway } = require("../../models");
const sequelize = require("../../models").sequelize;
const Op = sequelize.Op;
const list = await Subway.findAll({
where: {
station_name_kr: {
[Op.like]: '%' + req.params.filter + '%',
},
},
attributes: [
'idx',
'station_line',
'station_name_kr'
],
});
But it didn't work....
Could you tell me what is the problem?
Edit 1
// models/subway.js
const Sequelize = require('sequelize');
module.exports = class Subway extends Sequelize.Model {
static init(sequelize){
return super.init({
idx: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
station_code: {
type: Sequelize.CHAR(20),
},
station_name_kr: {
type: Sequelize.CHAR(20),
allowNull: false,
},
station_name_en: {
type: Sequelize.CHAR(30),
},
station_line: {
type: Sequelize.CHAR(10),
},
outside_code: {
type: Sequelize.CHAR(10),
},
}, {
sequelize,
timestamps: true,
underscored: true,
paranoid: true,
modelName: 'subway',
tableName: 'Subway',
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
};
The problem in your code is that you are mistaking two things.
First one:
Sequelize object from requiring library.
Second one:
sequelize connection from "instantiating" the Sequelize Object.
Note the upper case and lower case (s)(S)equelize because they represent two distinct objects.
Below what you are trying to do is access the connection and from there the Operator (Op) property. It is not going to work. The sequelize connection does NOT have it.
const sequelize = require("../../models").sequelize;
const Op = sequelize.Op;
To be able to access you should do the following:
const Sequelize = require('sequelize');
const Op = sequelize.Op;
That is why your answer "works". But that answer is not why it works.
Oh the answer was very simple...
I just initialize a Op object like this.
const Op = require("sequelize").Op;
Then, I could use the Op object with like, or , and etc...

Sequelize defining tables pluralized when using sync

I've written migrations to define my tables in a seperate service. Im then using a node.js service to run sequelize where i'm defining my models like this:
import Sequelize from "sequelize";
import sequelize from "../config/sequelize";
export const MasterPlaylist = sequelize.define("Master_playlist", {
id: { type: Sequelize.STRING, primaryKey: true },
updated_at: {
type: Sequelize.DATE,
defaultValue: new Date(),
allowNull: false,
},
});
Im then importing this and calling it like so:
import Sequelize from "sequelize";
import sequelize from "./config/sequelize";
import { Label } from "./models/Label";
async function run(){
await sequelize.sync();
const label = await Label.findOne();
console.log("done", label);
}
run()
Have simplified things slightly here, but this is whats being run.
When i run this it creates new tables but pluralised so i end up with the correctly named tables as inserted by the migrations and then pluralised copies.
For example for this table i end up with 'Master_playlists'
Anyone got an idea whats happening here?
here is my config file:
import Sequelize from "sequelize";
const sequelize = new Sequelize(
process.env.DB,
process.env.USERNAME,
process.env.PASSWORD,
{
host: process.env.HOST,
dialect: "postgres",
}
);
async function run() {
await sequelize.authenticate();
}
run();
export default sequelize;
Not exactly sure what the issue is, but sequelize uses inflection to pluralize table names.
By default, when the table name is not given, Sequelize automatically pluralizes the model name and uses that as the table name. This pluralization is done under the hood by a library called inflection, so that irregular plurals (such as person -> people) are computed correctly.
You can control the table names directly using freezeTableName: true which will keep the table name the same as model name:
sequelize.define('User', {
// ... (attributes)
}, {
freezeTableName: true
});
or specify the table name explicitly:
sequelize.define('User', {
// ... (attributes)
}, {
tableName: 'users'
});

"defineCall is not a function". Using sequelize with Node.JS

I'm learning how to use Sequelize for a Node.JS project, I'm working on the models:
index.js
var Sequelize = require('sequelize');
const sequelize = new Sequelize('mysql://bf3a13a7df5b2f:e2707ede#us-cdbr-iron-east-03.cleardb.net/heroku_6bdb0d8ad6c6a50?reconnect=true');
// load models
var models = [
'student',
];
models.forEach(function(model) {
module.exports[model] = sequelize.import(__dirname + '/' + model);
});
// export connection
module.exports.student= student;
module.exports.sequelize = sequelize;
student.js
var sequelize = require('./dbConnection');
var Sequelize = require('sequelize');
const student = sequelize.define('student', {
id: {
type: Sequelize.STRING,
primaryKey: true
},
name: {
type: Sequelize.STRING
},
middleName: {
type: Sequelize.STRING
},
lastName: {
type: Sequelize.STRING
},
dob: {
type: Sequelize.DATE
},
//student.sync({force: true});
});
module.exports = student;
and this is the error message I receive from the command line:
C:\Users\adria\OneDrive\Documentos\GitHub\ScholarMean1\node_modules\sequelize\lib\sequelize.js:691
this.importCache[path] = defineCall(this, DataTypes);
^
TypeError: defineCall is not a function
I managed to make it work if the model is in index.js, but because I want to make a file for each model I hope you can help me.
I saw a similar problem just now and the problem was a file that was in the models folder that was not actually a database model. Ensure that your models folder only contains models for your database. Hopefully this helps!

how to import modules that require arguments

this is my files sturcture:
-models
-user.js
-room.js
-database.js
-controllers
-createRoom.js
-routes.js
..
user.js and room.js are modules i want to import in database.js. right now im doing like this:
in database.js:
var mysql = require('mysql');
var Sequelize = require('sequelize');
var db = new Sequelize('test', 'root', 'root', {
dialect: "mysql",
port: 3306
})
var User = require('./user.js')(Sequelize, db);
var Room = require('./room.js')(Sequelize, db);
module.exports = function(){
//code...
};
in user.js/room.js
module.exports = function (Sequelize, db) {
var Room = db.define('Room', {
room_id : {type: Sequelize.INTEGER, allowNull: false, autoIncrement: true, primaryKey: true},
})
db
.sync({force: true})
.complete(function (err) {})
so far so good, but when i need to import user.js or room.js in other files besides database.js(eg, createRoom.js), i have trouble importing them because theres no Sequelize and db defined like in the database.js. does it mean i have to connect to the database and require Sequelize again whenever i need to use user.js and room.js module in other files? is there a better way to work around this?? thanks!
you have different possibilities here
re-export models:
in your database.js
//init code as seen
module.exports.Room = Room
importing somewhere else
require('../models/database').Room
make your database.js dependency
in database.js
module.export = { Sequelize: Sequelize, db : db}
in room.js
var dbModule = require('./database')
module.exports = dbModule.Sequelize.define('Room', /*....*/)
Attach the model to the init function
in room.js
module.exports = roomInit
function roomInit(Sequelize, db) {
roomInit.Room = db.define('Room', {
room_id : {type: Sequelize.INTEGER, allowNull: false, autoIncrement: true, primaryKey: true}
})
db
.sync({force: true})
.complete(function (err) {})
}
usage
require('./room').Room

Resources