Set safe-deleting mode for relations table in Sequelize.js - mysql

So, assume we have that Sequelize model:
var User = sequelize.define("User", {
id: {
type: DataTypes.STRING(45),
allowNull: false,
primaryKey: true
},
password: {
type: DataTypes.STRING(60),
allowNull: false
},
email: {
type: DataTypes.STRING(45),
allowNull: false,
unique: true
},
firstName: {
type: DataTypes.STRING(45),
allowNull: true,
defaultValue: null
}
},
{
tableName: 'profiles',
classMethods: {
associate: function(models) {
User.belongsToMany(User, {through: 'friends', as:'friend'});
}
}
});
after calling associate() method, it will create an extra table friends with columns userId, friendId, createdAt and updatedAt. The case is I need to use this table with safe-deleting mode, in other words, I have to add 'deleted' column somehow. I tried to use paranoid: true in belongsToMany's attributes, didn't work. Is there any ways to do it?

Maybe you can create an model/table which name is Friend. And you can set paranoid: true in that model. And when you deleted an User, it keeps User's friend relation was keeping in that model.
I hope it works. :)

Related

I created oneToMany relation but how I can get the single record belongs to the many record in Sequalize

Tagcategories Model
export const TagCategories = sequelize.define(
"tag_categories",
{
categoryId: {
type: DataTypes.INTEGER,
field: "category_id",
autoIncrement: true,
primaryKey: true,
},
title: {
type: DataTypes.STRING(50),
field: "title",
allowNull: false,
unique: true,
},
},
);
TagCategories.hasMany(TagGroups, {
foreignKey: "categoryId",
sourceKey: "categoryId",
});
export default TagCategories;
TagGroups Model
export const TagGroups = sequelize.define(
"tag_groups",
{
tagGroupId: {
type: DataTypes.INTEGER,
field: "tag_group_id",
autoIncrement: true,
primaryKey: true,
},
categoryId: {
type: DataTypes.INTEGER,
field: "category_id",
allowNull: false,
},
title: {
type: DataTypes.STRING(50),
field: "title",
allowNull: false,
unique: true,
},
},
);
In the above models I establish oneToMany relationship between the TagCategories and TagGroups
But I want to fetch the record from the TagGroup table with the TagCategories details.
Thanks in advance
Did you look at examples in official documentation?
Also, you need to add an association from TagGroups to TagCategories:
// there is no need to indicate `sourceKey` if this field is a primary key
TagGroups.belongsTo(TagCategories, {
foreignKey: "categoryId",
});
It's better to define all associations in static functions and call all of them separately after all models will be registered.
See the question and my answer here how to do it
In your case, the final request would be something like this
const tagGroup = await TagGroups.findOne({
where: {
tagGroupId: groupId
},
include: [{
model: TagCategories
}]
})

FeathersJs: Check if user is item creator or creator of associated item

I have two services: posts and comments. Every post can have multiple comments. User 1 creates a post, user 2 creates a comment inside this post. Both users should be able to update, patch or delete the created comment. How do I correctly qualify both users to modify the comment created by user 2?
Posts model
{
userId: { type: DataTypes.INTEGER, allowNull: false },
text: { type: DataTypes.TEXT, allowNull: false },
};
posts.associate = function (models) {
posts.hasMany(models.comments, { onDelete: 'CASCADE' });
}
Comments model
{
userId: { type: DataTypes.INTEGER, allowNull: false },
postId: { type: DataTypes.INTEGER, allowNull: false },
text: { type: DataTypes.TEXT, allowNull: false },
};
comments.associate = function (models) {
comments.belongsTo(models.posts);
}
Posts can only be deleted by the post-creator, so setField from the feathers-authentication-hooks does a good job in this case. But how do I qualify the post-creator to manage comments inside his post?

Sequelize relations foreign key constraint

I have a post route that is using the sequelize create method to add an event to the database. I have defined the tables for user and event as such:
Events
const Events = sequelize.define('Events', {
Event_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
month: {
type: DataTypes.STRING,
allowNull: false
},
day:{
type:DataTypes.INTEGER,
allowNull: false
},
year: {
type: DataTypes.INTEGER,
allowNull: false
},
important:{
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
description:{
type: DataTypes.STRING,
allowNull: true
}
});
return Events;
}
User
const User = sequelize.define('Users', {
user_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
}
}, {});
User.associate = function(models){
User.hasMany(models.Events, {as: 'user'})
}
return User;
}
The post route seems to run correctly with the exception on sequelize not being able to attach the user Id to the event that is created do to
"Cannot add or update a child row: a foreign key constraint fails (planitdb.events, CONSTRAINT events_ibfk_1 FOREIGN KEY (UserUserId) REFERENCES users (user_id) ON DELETE SET NULL ON UPDATE CASCADE)"
I am not sure I understand exactly why this is happening. I am thinking I need to define the relation in the Events table as well? If that is the case, I am not sure I understand what type of relationship the Events table has with the User table. Or is the relationship a single event to a single user?
Any help would be greatly appreciated.
Your events object does not contain a mapping for user_id. This object needs to include a user_id field and this needs to be populated prior to attempting to insert a record to the events table.
EDIT - including sequelize relations solution:
Instead of this:
const Events = sequelize.define('Events', {...});
User.associate = function(models){
User.hasMany(models.Events, {as: 'user'})
}
Try:
const Events = sequelize.define('Events', {...});
const User = sequelize.define('User', {...});
User.hasMany(Events, {as: 'user'});
or:
const Events = sequelize.define('Events', {});
const User = sequelize.define('User', {...});
Events.belongsTo(User,{
foreignKey: 'user_id',
constraints: false,
as: 'user'
});

sequelize - how to update an association in n-m relation including join table

I have two tables (user, tag) that are connected to each other with a belongsToMany relationship through a join entity (user_tag):
sequelize.define('tag', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
type: {
type: DataTypes.STRING
}
}, {
classMethods: {
associate: function (models) {
this.belongsToMany(models.user, {as: "users", through: models.user_tag });
},
}
}
sequelize.define('user', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING,
},{
classMethods: {
associate: function (models) {
this.belongsToMany(models.tag, { as:"tags", through: models.user_tags });
}
}
}
sequelize.define('user_tag', {
type: DataTypes.STRING,
param1: DataTypes.INTEGER,
priority: DataTypes.INTEGER
}, {
freezeTableName: true,
paranoid: true
});
Now, a user can update all his tags, including all the specific information on the join entity (user_tag) for example priority and param1.
I'm aware of setAssociation [ e.g. user.setTag(myTags) ], however, how do I set the matching param1 and priority properties?
According to Sequelize's documentation when adding a new relationship with belongsToMany, you can pass in additional attributes to the option object and that data will get added to the through model.
user.setTag(myTags, { param1: 1, priority: 1 });

Sequelize hasMany association issue

In my application a user can have several module which is stored in the user_has_module table. This means that for each user_has_module row, I want to include module where the module_id matches.
module
Module = sequelize.define('module', {
academy_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
module_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
module_module_type_id: DataTypes.INTEGER,
sort_number: DataTypes.INTEGER,
score_to_pass: DataTypes.INTEGER
}, {
freezeTableName: true
})
user_has_module
User_has_module = sequelize.define('user_has_module', {
user_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
module_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
academy_team_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
academy_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
sort_number: DataTypes.INTEGER,
is_complete: DataTypes.INTEGER,
score_to_pass: DataTypes.INTEGER,
is_open: DataTypes.INTEGER,
deadline: DataTypes.DATE
}, {
freezeTableName: true
})
My relation
User_has_module.belongsTo(Module, {foreignKey: 'module_id'});
Now what I want to do is join them on module.module_id = user_has_module.module_id.
My problem is that module has, as you can see, two primary key, and when sequelize joins these two tables, it chooses academy_id as its primary key.
My question is, is there a way to tell Sequelize that in this relation it has to choose the primary key module_id from module?
I think you don't need a model called User_has_module.
I assume you have one model called User and one model call Module.
So you should have designed something like this:
var User = sequelize.define("User", {
name: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
User.hasMany(models.Module);
}
}
});
And for your Module:
var Module = sequelize.define("Module", {
name: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
Module.belongsToMany(models.User);
}
}
});
To get a User with its Modules you can do this:
models.User.findAll({ include: [models.Module]}).then(function(users){
console.log(users);
});
Hope I got your question right and it helps.
Cheers