LoginSignup
0
0

More than 5 years have passed since last update.

[Express.js][Sequelize] 親レコードの削除時に子レコードも削除( cascade削除 )する

Posted at

Express.js(ejs) + Sequelize(MySQL)でrailsのscaffoldアプリを作る の記事を参考に User (親) と 各 User に紐付く Comment (子) の構成を持つアプリケーションを作りました。

このアプリケーションにて、親の User を削除した際に、その User に紐付く子の Comment 群も削除する Cascade 削除を行う方法でハマったので記録します。

環境

  • Node.js: v10.5.0
  • Express.js: 4.16.0
  • Sequelize: 4.0.0
  • MySQL: 5.6.40

採用した方法 ( migration の addConstraint で cascade 定義する )

migration の addConstraint で cascade 定義した foreign key を設定します。

まず、 migration を新規作成します。

$ sequelize migration:create --name AddConstraintToComment
migrations/20180728081647-AddConstraintToComment.js
'use strict';

module.exports = {
  up: (queryInterface, Sequelize) => {
    /*
      Add altering commands here.
      Return a promise to correctly handle asynchronicity.

      Example:
      return queryInterface.createTable('users', { id: Sequelize.INTEGER });
    */
    return Promise.all([
      queryInterface.addConstraint('Comments', ['user_id'], {
        type: 'foreign key',
        name: 'fk_comments_users',
        references: {
          table: 'Users',
          field: 'id'
        },
        onDelete: 'cascade',
        onUpdate: 'cascade'
      })
    ]);
  },

  down: (queryInterface, Sequelize) => {
    /*
      Add reverting commands here.
      Return a promise to correctly handle asynchronicity.

      Example:
      return queryInterface.dropTable('users');
    */
    return queryInterface.removeConstraint('Comments', 'fk_comments_users');
  }
};

addConstraint のオプションで onDelete : 'cascade' を指定するところがポイントです。

migration を実行します。

$ sequelize db:migrate

実行が成功すると、以下のようなテーブル定義になっていることが確認できます ( MySQL にて)。

mysql> show create table Comments;
+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                   |
+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Comments | CREATE TABLE `Comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `content` text,
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_comments_users` (`user_id`),
  CONSTRAINT `fk_comments_users` FOREIGN KEY (`user_id`) REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 |
+----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

CASCADE 制約によって、 User を 削除した時に、紐付く Comment も削除されるようになります。

動かなかった方法

マニュアルチュートリアルStack Overflow などによると、 model にて、 hasMany メソッドに次のように onDelete オプションと hooks オプションを与えれば cascade 削除が動くようなのですが、動作しませんでした。

Users.hasMany(Comments, { onDelete: 'cascade', hooks: true });

より、具体的な記述は次の通りです。

models/user.js
'use strict';
module.exports = (sequelize, DataTypes) => {
  var User = sequelize.define('User', {
    name: DataTypes.STRING,
    age: DataTypes.INTEGER
  }, {});
  User.associate = function(models) {
    // associations can be defined here
    User.hasMany(models.Comment, {
      foreignKey: 'user_id',
      onDelete: 'cascade',
      hooks: true
    });
  };
  return User;
}

何か知見をお持ちの方があれば、ご教示いただけるとありがたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0