I have a many to many relationship between the tables DeliveryOrder and GasBottle with the extra field Amount, but when i try to insert some values in this table, sequelize change´s the field order.
My models:
const {Model,DataTypes} = require ('sequelize')
class GasBottle extends Model{
static init(sequelize){
super.init({
type: DataTypes.INTEGER,
costPrice: DataTypes.DOUBLE,
sellPrice: DataTypes.DOUBLE
},{sequelize})
}
static associate({ DeliveryOrder,DeliveryOrderGasBottle}) {
GasBottle.belongsToMany(DeliveryOrder, {
through: DeliveryOrderGasBottle,
as: "deliveryOrders",
foreignKey: "deliveryOrderId",
});
}
}
module.exports = GasBottle
const { Model, DataTypes } = require("sequelize");
class DeliveryOrder extends Model {
static init(sequelize) {
super.init(
{
status: DataTypes.INTEGER,
latitude: DataTypes.INTEGER,
longitude: DataTypes.INTEGER,
delivererId: {
type: DataTypes.INTEGER,
references: {
model: "Deliverer",
key: "id",
},
},
},
{ sequelize }
);
}
static associate({ Deliverer, GasBottle, DeliveryOrderGasBottle }) {
DeliveryOrder.belongsTo(Deliverer, { foreignKey: "delivererId" });
DeliveryOrder.belongsToMany(GasBottle, {
through: DeliveryOrderGasBottle,
as: "bottles",
foreignKey: "gasBottleId",
});
}
}
module.exports = DeliveryOrder;
const { Model, DataTypes } = require("sequelize");
class DeliveryOrderGasBottle extends Model {
static init(sequelize) {
super.init(
{
gasBottleId: {
type: DataTypes.INTEGER,
references: {
model: "GasBottle",
key: "id",
},
},
deliveryOrderId: {
type: DataTypes.INTEGER,
references: {
model: "DeliveryOrder",
key: "id",
},
},
amount: DataTypes.INTEGER,
},
{ sequelize }
);
}
}
module.exports = DeliveryOrderGasBottle;
My migration file:
"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable("DeliveryOrderGasBottle", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
gasBottleId: {
type: Sequelize.INTEGER,
references: {
model: "GasBottle",
key: "id",
},
allowNull: false,
onDelete: "CASCADE",
},
deliveryOrderId: {
type: Sequelize.INTEGER,
references: {
model: "DeliveryOrder",
key: "id",
},
allowNull: false,
onDelete: "CASCADE",
},
amount:{
type: Sequelize.DOUBLE,
allowNull: false,
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable("DeliveryOrderGasBottle");
},
};
My association:
const deliveryOrder = await DeliveryOrder.create(obj);
bottlesToAdd.map(async (bottle) => {
const db_bottle = await GasBottle.findByPk(bottle.id);
await deliveryOrder.addBottle(db_bottle, {
through: { amount: parseInt(bottle.amount) },
});
On insert, sequelize is changing the order of the ids, resulting in a constraint error because i dont have the id´s on the respective tables
INSERT INTO "DeliveryOrderGasBottle" ("gasBottleId","deliveryOrderId","amount","createdAt","updatedAt") VALUES (18,1,42,'2020-06-27 19:17:26.204 +00:00','2020-06-27 19:17:26.204 +00:00')
Related
sirs. I have 2 models in sequelize ,Project and User. Relationship between this two models is many-to-many. Fot this relation, I have created projectuser. But when i trying to insert intoprojectuser console gives me ReferenceError: Cannot access 'projectuser' before initialization error. [NodeJs][Sequelize] ReferenceError: Cannot access 'ModelName' before initialization I have tried this solution but i think it is too complex solution. Can you please help me?
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Project extends Model {
static associate(models) {
const { User, Issue, projectuser } = models;
this.belongsToMany(User, {
as: "project_users",
foreignKey: "project_id",
through: "projectuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.hasMany(Issue, {
as: "project_issues",
foreignKey: "project_id",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
Project.init(
{
project_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
projectname: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
},
projecturl: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "Project",
}
);
return Project;
};
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
const { Commet, Project, Issue, projectuser, issueuser } = models;
this.hasMany(Commet, {
foreignKey: "user_id",
as: "user_commets",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.belongsToMany(Project, {
as: "project_user",
foreignKey: "user_id",
through: "projectuser",
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
this.belongsToMany(Issue, {
as: "user_issues",
foreignKey: "user_id",
through: issueuser,
onDelete: "CASCADE",
onUpdate: "CASCADE",
});
}
}
User.init(
{
user_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
role: {
type: DataTypes.STRING,
allowNull: false,
validate: {
roleValidator(role) {
let rolet = role.toLowerCase();
if (roles[rolet] === undefined) {
throw new Error("Invalid Role");
}
},
},
},
username: { type: DataTypes.STRING, allowNull: false },
usersurname: { type: DataTypes.STRING, allowNull: false },
avatarURL: { type: DataTypes.STRING, allowNull: true },
password: {
type: DataTypes.STRING,
validate: {
passwordValidator(password) {
if (password.length <= 5) {
throw new Error("Cannot be less than 5 characters");
}
},
},
},
email: {
type: DataTypes.STRING,
unique: true,
validate: { isEmail: true },
},
},
{
sequelize,
modelName: "User",
}
);
return User;
};
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class projectuser 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
}
}
projectuser.init({
deneme: DataTypes.STRING
}, {
sequelize,
modelName: 'projectuser',
});
return projectuser;
};
When I try to insert new category, I got this error:
error: column "image" does not exist
sql: 'INSERT INTO "Categories" ("id","createdAt","updatedAt") VALUES (DEFAULT,$1,$2) RETURNING "id","image","title","createdAt","updatedAt";'
The problem is that it doesn't insert name and other values and returns columns belong to post table.
My guesses are the problem of sequelize-cli and sequelize version or missing something in models or migrations.
I only insert values into name, createdAt and updatedAt column:
await Category.create({
name: req.body.name,
createdAt: new Date(),
updatedAt: new Date()
});
My category model:
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Category extends Model {
static associate(models) {
Category.hasMany(models.Post, { as: "posts", foreignKey: "categoryId" });
}
}
Category.init(
{
name: DataTypes.STRING
},
{
sequelize,
modelName: "Category"
}
);
return Category;
};
My Post Model:
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Post extends Model {
static associate(models) {
Post.belongsTo(models.Category, { foreignKey: "categoryId", onDelete: "CASCADE", as: "category" });
}
}
Post.init(
{
title: DataTypes.STRING,
image: DataTypes.STRING,
content: DataTypes.TEXT,
categoryId: DataTypes.INTEGER
},
{
sequelize,
modelName: "Post"
}
);
return Post;
};
Post migration:
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("Posts", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
image: {
type: Sequelize.STRING
},
content: {
type: Sequelize.TEXT
},
categoryId: {
type: Sequelize.INTEGER,
allowNull: false,
onDelete: "CASCADE",
references: {
model: "Categories",
key: "id"
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
Category migration:
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("Categories", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
I couldn't find solution for this, therefor I used sequelize.query
I have a user, role and their relation model, when I want to insert into the relation model I get this error:
error: column "userUserId" of relation "roles_users_relationships" does not exist.
Can you help with this error?
(sorry if I wrote something wrong, this is my first question on )
This is how my model looks
Role model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles", {
role_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsToMany(models.users, {
through: "roles_users_relationship",
foreignKey: "role_id",
});
};
return table;
};
Users model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"users", {
user_id: {
type: DataTypes.UUID,
defaultValue: sequelize.literal("uuid_generate_v4()"),
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: true,
}
}, {
timestamps: false
}
);
table.associate = function (models) {
table.belongsTo(models.roles, {
through: "roles_users_relationship",
foreignKey: "user_id",
});
};
return table;
};
Roles Users relationship model:
const Schema = (sequelize, DataTypes) => {
const table = sequelize.define(
"roles_users_relationship", {
user_id: {
type: DataTypes.UUID,
allowNull: false,
},
role_id: {
type: DataTypes.UUID,
allowNull: false,
},
}, {
timestamps: false
}
);
return table;
};
In your through table you should add options in related table field:
references: {
model: User,
key: 'user_id'
}
Otherwise sequelize will do it automatically, like adding foreign key column in this way tableNamePrimaryKeyColumn in your case its 'userUserId'
I have a problem with migrating two tables with relationships. I want to add a foreign key to product.js migration, but it is not working. If I will run the application with await sequelize.sync(); database creating well.
How to fix this issue? I did the same thing with another migrations user and addresses, and it worked as I expected. Appreciate your help.
== 20210124144301-create-product: migrating =======
ERROR: Can't create table database_development.products (errno:
150 "Foreign key constraint is incorrectly formed")
create-category.js migration:
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("сategories", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
description: Sequelize.TEXT,
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("сategories");
},
};
create-product.js migration:
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("products", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
categoryId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: "categories",
key: "id",
},
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
description: {
type: Sequelize.TEXT,
allowNull: false,
},
price: {
type: Sequelize.DOUBLE(11, 2).UNSIGNED,
defaultValue: 0,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("products");
},
};
category.js model:
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Category 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) {
this.hasMany(models.Product, {
foreignKey: "categoryId",
});
}
}
Category.init(
{
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
description: DataTypes.TEXT,
},
{
sequelize,
tableName: "categories",
modelName: "Category",
}
);
return Category;
};
product.js model:
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Product 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) {
this.belongsTo(models.Category, {
foreignKey: "categoryId",
});
}
}
Product.init(
{
name: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
allowNull: false,
},
price: {
type: DataTypes.DOUBLE(11, 2).UNSIGNED,
defaultValue: 0,
},
},
{
sequelize,
tableName: "products",
modelName: "Product",
}
);
return Product;
};
You need to add primary key(id) in your product and category model file also change your model associations .
product.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Product 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) {
Product.belongsTo(models.Category, {
foreignKey: "categoryId",
});
}
}
Product.init(
{
productId: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
allowNull: false,
},
price: {
type: DataTypes.DOUBLE(11, 2).UNSIGNED,
defaultValue: 0,
},
categoryId: {
type: DataTypes.INTEGER
}
},
{
sequelize,
tableName: "products",
modelName: "Product",
}
);
return Product;
};
Category.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Category 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) {
Category.hasMany(models.Product, {
foreignKey: "categoryId",
});
}
}
Category.init(
{
categoryId: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
description: DataTypes.TEXT,
},
{
sequelize,
tableName: "categories",
modelName: "Category",
}
);
return Category;
};
the foreign key must be the same type of the primary key on the other table
I am trying to delete all contents from a n:m association table.
I have the tables: MenuItems and UserGroups like this, but I am using migrations to genererate the database:
MenuItems
module.exports = (sequelize, DataTypes) => {
const MenuItems = sequelize.define('MenuItems', {
title: {
type: DataTypes.STRING,
allowNull: false
}
// more fields...
}, {
freezeTableName: true
});
MenuItems.associate = function(models) {
MenuItems.belongsToMany(models.UserGroups, { through: 'MenuItemUserGroups' });
};
UserGroups
module.exports = (sequelize, DataTypes) => {
const UserGroups = sequelize.define('UserGroups', {
name: {
type: DataTypes.STRING,
unique: true
}
}, {
freezeTableName: true
});
UserGroups.associate = function(models) {
// Associations to other models
UserGroups.belongsToMany(models.MenuItems, { through: 'MenuItemUserGroups' });
};
return UserGroups;
};
The association table is generated with the following migration:
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('MenuItemUserGroups', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
menuItemId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'MenuItems',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
},
userGroupId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'UserGroups',
key: 'id'
},
onUpdate: 'cascade',
onDelete: 'cascade'
}
//more fields
});
}
I try to delete using the following sequelize code:
models.MenuItems.findOne({ where: { id: 1 }, include: [{ all: true }] }).then(menuItem => {
if(req.body.userGroups.length <= 0) {
menuItem.setUserGroups([]).then(result => {
console.log(result);
});
The SQL that is generated is the following:
DELETE FROM `MenuItemUserGroups` WHERE `UserGroupId` = 1 AND `MenuItemId` IN (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
[ 0 ]
where UserGroupId IN (NULL) will always return nothing. If that part is removed, the query works.
Could this have something to do with some naming convention?