'How to delete associated rows with sequelize

I am trying to delete rows associated with a row in a table, without deleting the main row (thus can't use CASCADE).

This is the raw PostgreSQL query that does what I want to achieve with SQL. Is sequelize able to generate such query:

DELETE FROM session USING user WHERE session.user_id = user.id AND user.username = 'bob'

The model is (not including irrelevant columns):

create table user (
  id uuid primary key default uuid_generate_v4(),
  username text UNIQUE NOT NULL
);

create table session (
  id uuid primary key default uuid_generate_v4(),
  user_id uuid NOT NULL references user(id) ON DELETE CASCADE
);

The association is defined in sequelize as:

Session.belongsTo(models.User, {
  foreignKey: "user_id"
});

User.hasMany(models.Session, {
  foreignKey: "user_id"
});

An alternative version of the query could be:

DELETE FROM session WHERE session.user_id = (SELECT user_id FROM user WHERE username = 'bob');

But I think sequelize doesn't handle subqueries yet?

I tried something along the lines:

return Session.destroy({
  include: [
    { model: User, where: { username: 'bob' }}
  ],
  truncate: false
});

However, sequelize complains:

Error: Missing where or truncate attribute in the options parameter of model.destroy.



Solution 1:[1]

If anyone gets here, this is how I "delete associated rows with sequelize": little help from the library:

  1. Read the user from db (Users.findOne({ ... }))
  2. call the method setSessions(array) provided by sequelize (the name depends on your model) which returns a promise.
/** @param {string} username */
const clearUserSessions = async (username) {
  const userInstance = await Users.findOne({ 
    where: { username }, 
    include: ['sessions'] 
   })
   if (!userInstance) {
    /* user not found */
    return ...
   }
   await userInstance.setSessions([])
   /* removed every session from user */
   return ...
};

later:

try {
  await clearUserSessions('bob')
} catch(err) {
 ...
}

Solution 2:[2]

return Session.destroy({
    where: {
        '$users.username$': 'bob'
    },
    include: [{
        model: User,
        as: 'users'
    }],
});

Hope that helps. Try to reach me with comment.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2