Hello I am new to nodejs and currently I integrated Sequelize with NodeJs. I make different models and define associations but when I fetch data then I received following error
TypeError: include.model.getTableName is not a function
My Box Model
const Sequelize = require('sequelize');
const PostBox = require("./PostBox");
module.exports = function (sequelize) {
var Box = sequelize.define('box', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
references: {
model: PostBox,
key: "box_id" // this is the `posts.post_id` column - name it according to your posts table definition (the one defined in ./Post)
}
}
}, {timestamp: false});
Box.associate = function (models) {
Box.hasMany(models.PostBox, {targetKey: 'user_posts_id',foreginkey: 'id'});
};
return Box;
};
Post Box Model
const Sequelize = require('sequelize');
var Post = require('./Post');
module.exports = function (sequelize) {
var PostBox = sequelize.define('user_posts_boxes', {
id: {
type: Sequelize.INTEGER,
primaryKey: true
},
user_posts_id: {
type: Sequelize.INTEGER,
references: {
model: Post,
key: "id" // this is the `posts.post_id` column - name it according to your posts table definition (the one defined in ./Post)
}
},
box_id: {
type: Sequelize.INTEGER,
},
user_id: {
type: Sequelize.INTEGER
},
post_type_id: {
type: Sequelize.INTEGER
}
}, {timestamp: false}
);
PostBox.associate = function (models) {
PostBox.belongsTo(models.Post, {targetKey: 'id', foreignKey: 'user_posts_id'});
};
return PostBox;
};
This is my base model from where I am calling associated model
const Sequelize = require('sequelize');
var Box = require('./Box');
const sequelize = new Sequelize('store_db', 'root', 'root', {
host: 'localhost',
dialect: 'mysql'
});
const User = require("./User")(sequelize);
const PostBox = require("./PostBox")(sequelize);
const Post = require("./Post")(sequelize);
function findOneUer() {
return User.findOne({attributes: ['id', 'username']});
}
function findPostById(id) {
var post = PostBox.findOne({
attributes: ['id', "user_posts_id", "box_id"],
where: {id: id},
include: [
{model: Box, required: true}
]
});
return post;
}
module.exports = {findPostById: findPostById};
When I call findPostById(2) method from my base mode then I received this error.
Related
(Update below)
I'm trying to set up model associations using Sequelize and the .associate method.
I have the setup below but this returns an error:
UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError:
ProductMember is not associated to Product!
What am I doing wrong?
Db setup:
const { Sequelize } = require("sequelize");
const config = require("./db.config.js");
const sequelize = new Sequelize(config[process.env]);
module.exports = sequelize;
db.config.js:
module.exports = {
development: {
database: DB_NAME,
username: DB_USER,
password: DB_PASS,
dialect: DB_DRIVER,
logging: false,
options: {
host: DB_HOST,
port: DB_PORT,
pool: {},
},
},
}
/models/product.js:
const { DataTypes } = require("sequelize");
const sequelize = require("../db");
const Product = sequelize.define(
"Product",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
name: {
type: DataTypes.STRING(255),
unique: true,
allowNull: false,
},
}
{
tableName: "products",
}
}
Product.associate = (models) => {
Product.belongsToMany(models.User, {
through: models.ProductMember,
foreignKey: "product_id",
otherKey: "user_id",
});
Product.hasMany(models.ProductMember, {
foreignKey: "product_id",
allowNull: false,
});
};
module.exports = sequelize.model("Product", Product);
models/user.js:
const { DataTypes } = require("sequelize");
const sequelize = require("../db");
const User = sequelize.define(
"User",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
email: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
isEmail: true,
},
username: {
type: DataTypes.STRING(15),
allowNull: false,
unique: true,
},
},
{
tableName: "users",
}
);
User.associate = (models) => {
User.belongsToMany(models.Product, {
through: models.ProductMember,
foreignKey: "user_id",
otherKey: "product_id",
});
User.hasMany(models.ProductMember, {
foreignKey: "user_id",
allowNull: false,
});
User.belongsToMany(models.Product, {
through: models.UserFavouriteProducts,
foreignKey: "user_id",
otherKey: "product_id",
});
}
module.exports = sequelize.model("User", User);
models/productMember.js:
const { DataTypes } = require("sequelize");
const sequelize = require("../db");
const ProductMember = sequelize.define(
"ProductMember",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
isAdmin: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
},
{
tableName: "product_members",
}
);
ProductMember.associate = (models) => {
ProductMember.belongsTo(models.User);
ProductMember.belongsTo(models.Product);
};
module.exports = sequelize.model("ProductMember", ProductMember);
Update: Based on this post I updated the Db setup file to:
const fs = require('fs');
const path = require('path');
var basename = path.basename(module.filename);
const models = path.join(__dirname, '../models');
const db = {};
const Sequelize = require("sequelize");
const config = require("./db.config.js");
const sequelize = new Sequelize(config[process.env]);
fs
.readdirSync(models)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(function (file) {
var model = require(path.join(models, file))(
sequelize,
Sequelize.DataTypes
);
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;
Model file:
module.exports = (sequelize, Sequelize) => {
const Coupon = db.sequelize.define(
//... continue as it was
return Coupon;
}
So for the model file:
Wrapped it inside module.exports = (sequelize, Sequelize) => { }
return Coupon at the end
removed const sequelize = require("../db");
New problem: But with this new setup, Sequelize-related controller methods no longer work... For example for a controller file:
const User = require("../models/user");
const ensureLoggedIn = async (req, res, next) => {
...
const user = await User.findByPk(id);
it produces the error:
User.findByPk is not a function
I've tried adding const sequelize = require("../db"); to the controller file and then const user = await sequelize.User.findByPk(id); but that produced the same error.
I've tried adding const db = require("../db"); to the controller file and then const user = await db.sequelize.User.findByPk(id); but that produced the error "Cannot read property 'findByPk' of undefined".
First, you don't need to call sequelize.model to get a model that registered in Sequelize, you can just export a return value from sequelize.define:
const Product = sequelize.define(
"Product",
...
module.exports = Product;
Second, it seems you didn't call associate methods of all registered models.
Look at my answer here to get an idea of how to do it.
Update: to use models if you defined them like in my answer you need to access them like this:
const { sequelize } = require("../db");
const user = await sequelize.models.User.findByPk(id);
...
I have 2 tables, users and users_signature where the signature takes several applications and I need to make a select according to the application.
Models:
user
const { INTEGER } = require('sequelize');
const Sequelize = require('sequelize');
const database = require('../../config/db');
const User_has_signature = require('./user_has_signature');
const Usuario = database.define('usuario', {
usu_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
usu_rg: {
type: Sequelize.STRING,
},
},
{
freezeTableName: true,
createdAt: false,
updatedAt: false,
});
User.hasMany(User_has_signature, {as: 'user_has_signature'});
module.exports = User;
User_has_signature
const { INTEGER } = require('sequelize');
const Sequelize = require('sequelize');
const database = require('../../config/db');
const User_has_signature = database.define('user_has_signature', {
usu_has_signature_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
user_usu_id: {
type: Sequelize.STRING,
},
signature_aplicativo_signature_aplicativo_id: {
type: Sequelize.STRING,
},
signature_type_signature_type_id: {
type: Sequelize.STRING,
},
},
{
freezeTableName: true,
createdAt: false,
updatedAt: false,
});
User_has_signature.associate = (models) => {
User_has_signature.belongsTo(models.User,
{ foreignKey: 'user_usu_id', as: 'users' });
};
module.exports = User_has_signature;
Controller
UserController
const User = require("../../model/user/user")
const User_has_signature = require("../../model/user/user_has_signature")
async index(req, res){
const user = await User.findAll({
include: [{
model: User_has_signature,
foreignKey: 'user_usu_id',
through: {
where: {signature_ttype_signature_type_id: 3}
}
}]
})
res.status(200).json(user)
return
}
The error that is returning to me in the terminal is: (node:15168)
UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError:
user_has_signature is associated to usuario using an alias. You must
use the 'as' keyword to specify the alias within your include
statement
I think you have to specify the alias you have given when writing your query :
include: [{
model: User_has_signature,
foreignKey: 'user_usu_id',
as : 'users'
through: {
where: {signature_ttype_signature_type_id: 3}
}]
Either way I'm using Sequelize more in Typescript, so I'm not sure of the syntax.
The way it handles One to Many relationship isn't the clearest I've seen (Like Symfony or Spring)
I am using sequelize version:5.21.2, and has the following error: 'Tweet is not associated to User!'
Error: { SequelizeEagerLoadingError: Tweet is not associated to User!
at Function._getIncludedAssociation (D:\References\Youtube\Sequelize\sequelize-1-hour\node_modules\sequelize\lib\model.js:715:13)
at Function._validateIncludedElement (D:\References\Youtube\Sequelize\sequelize-1-hour\node_modules\sequelize\lib\model.js:619:53)
at options.include.options.include.map.include (D:\References\Youtube\Sequelize\sequelize-1-hour\node_modules\sequelize\lib\model.js:516:37)
at Array.map (<anonymous>)
I have two models
Tweet.js
const Sequelize = require('sequelize');
//sequelize comes from global.sequelize in connection.js
const Tweet = sequelize.define('Tweet', {
id: {
type: Sequelize.INTEGER(11),
allowNull: true,
autoIncrement: true,
primaryKey: true
},
userId: Sequelize.INTEGER(11),
content: Sequelize.STRING(300)
});
Tweet.associate = function(models) {
Tweet.belongsTo(models.User, { foreignKey: 'userId' });
};
module.exports = Tweet;
and User.Js
const Sequelize = require('sequelize');
//sequelize comes from global.sequelize in connection.js
const User = sequelize.define('User', {
id: {
type: Sequelize.INTEGER(11),
primaryKey: true
},
username: {
type: Sequelize.STRING(35),
},
passwd: {
type: Sequelize.STRING(20),
allowNull: false
}
});
User.associate = function(models) {
User.hasMany(models.Tweet);
};
module.exports = User;
and the code which throws error is
const users = await User.findAll({
where: { id: '1' },
include: [Tweet]
}).catch(errHandler);
I don't know how to include Tweets when a user is fetched.
You have defined functions, inside your models, that create your associations. However, you never call these functions. After instanciating your Sequelize object and initializing your models, you should run the following code to have your associations created:
for(let modelName in sequelize.models) {
sequelize.models[modelName].associate(sequelize.models);
}
See:
Sequelize models member
Iterating through objects in Javascript
i'm using NodeJS & Sequelize for a school project and i'm struggling on making associations w/ sequelize work. I tried a couple of things before but nothing that made my day.
Basically the thing is that a user can have several playlists (hasMany).
And a playlist belongs to a user (belongsTo).
My error is:
Association with alias "playlist" does not exist on users
Here are my models:
/* USER MODEL */
const Sequelize = require('sequelize');
const { db } = require('../utils/db');
const User = db.define('users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
userID: {
type: Sequelize.INTEGER,
allowNull: false,
field: 'user_id',
},
firstName: {
type: Sequelize.STRING,
field: 'first_name',
allowNull: false,
},
}, {
underscored: true,
tableName: 'users',
freezeTableName: true, // Model tableName will be the same as the model name
});
module.exports = {
User,
};
/* PLAYLIST MODEL */
const sequelize = require('sequelize');
const { db } = require('../utils/db');
const Playlist = db.define('playlist', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: sequelize.INTEGER,
},
name: {
type: sequelize.STRING,
field: 'name',
allowNull: false,
},
coverUrl: {
type: sequelize.STRING,
field: 'cover_url',
allowNull: true,
},
ownerId: {
type: sequelize.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'user_id',
},
},
}, {
underscored: true,
tableName: 'playlist',
freezeTableName: true,
});
module.exports = {
Playlist,
};
Here is how i load my models:
const { Credentials } = require('./credentials');
const { User } = require('./users');
const { Playlist } = require('./playlist');
function loadModels() {
User.associate = (models) => {
User.hasMany(models.Playlist, { as: 'playlist' });
};
Playlist.associate = (models) => {
Playlist.belongsTo(models.User, { foreignKey: 'owner_id', as: 'owner' });
};
Credentials.sync({ force: false });
User.sync({ force: false });
Playlist.sync({ force: false });
}
module.exports = {
loadModels,
};
And finally here is my query where i get this error:
const express = require('express');
const { auth } = require('../../middlewares/auth');
const { Playlist } = require('../../models/playlist');
const { User } = require('../../models/users');
const router = express.Router();
router.get('/playlist', [], auth, (req, res) => {
User.findOne({
where: { userID: req.user.user_id }, include: 'playlist',
}).then((r) => {
console.log(r);
});
});
module.exports = router;
I'm trying to get all the playlist that belongs to a user.
I removed all the useless code (jwt check etc..)
So when i'm doing a get request on /playlist I get:
Unhandled rejection Error: Association with alias "playlist" does not exist on users.
I understand the error but don't understand why i get this.
What did I miss, any ideas ?
Thanks,
I finally fixed it by re-make all my models and definitions with migrations.
I had the same problem and the solution was that Sequelize pluralize the models name so in my case "playlist" does not exist on users because Sequelize pluralized my model so I had to put "Playlists" instead.
I am trying to map sequelize one to many association by referring to sequelize documentation but I could not able to find a complete example to get it work.
I have a ClaimType model as follows
const Sequelize = require('sequelize');
module.exports = function (sequelize) {
const ClaimType = sequelize.define('claim_type', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: Sequelize.STRING
}
}, {
timestamps: false,
freezeTableName: true
});
return ClaimType;
};
and MaxClaimAmount
const Sequelize = require('sequelize');
module.exports = function (sequelize) {
const MaxClaimAmount = sequelize.define('max_claim_amount', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
amount: {
type: Sequelize.DECIMAL
},
year: {
type: Sequelize.INTEGER
}
}, {
timestamps: false,
freezeTableName: true
});
return MaxClaimAmount;
};
finally in index.js
const ClaimType = require('./model/claim_type.js')(sequelize);
const MaxClaimAmount = require('./model/max_claim_amount.js')(sequelize);
ClaimType.hasMany(MaxClaimAmount, { as: 'claimAmount' });
sequelize.sync({ force: false }).then(() => {
return sequelize.transaction(function (t) {
return ClaimType.create({
name: 'OPD'
}, { transaction: t }).then(function (claimType) {
// want to know how to associate MaxClaimAmount
});
}).then(function (result) {
sequelize.close();
console.log(result);
}).catch(function (err) {
sequelize.close();
console.log(err);
});
});
ClaimType object is returned from the first part of the transaction and I want to know how to implement the association between ClaimType and MaxClaimAmount?
You make the association in your models.
(Associations: one-to-many in sequelize docs)
const ClaimType = sequelize.define('claim_type', {/* ... */})
const MaxClaimAmount = sequelize.define('max_claim_type', {/* ... */})
ClaimType.hasMany(MaxClaimAmount, {as: 'MaxClaims'})
This will add the attribute claim_typeId or claim_type_id to MaxClaimAmount (you will see the column appear in your table). Instances of ClaimType will get the accessors getMaxClaims and setMaxClaims (so you can set foreign id on table)
The next step would be creating your backend routes and using the accessor instance methods to set a foreign key. The accessor functions are called like so: (instance1).setMaxClaims(instance2)
Instances are returned from queries