パラノイド
Sequelizeは、パラノイドテーブルの概念をサポートしています。パラノイドテーブルとは、レコードの削除を指示されたときに、実際には削除しないテーブルのことです。代わりに、deletedAt
という特別な列に、削除リクエストのタイムスタンプが設定されます。
これは、パラノイドテーブルが、ハード削除ではなく、レコードのソフト削除を実行することを意味します。
モデルをパラノイドとして定義する
モデルをパラノイドにするには、モデル定義にparanoid: true
オプションを渡す必要があります。パラノイドはタイムスタンプが動作するために必要です(つまり、timestamps: false
も渡すと動作しません)。
また、デフォルトの列名(deletedAt
)を別のものに変更することもできます。
class Post extends Model {}
Post.init(
{
/* attributes here */
},
{
sequelize,
paranoid: true,
// If you want to give a custom name to the deletedAt column
deletedAt: 'destroyTime',
},
);
削除
destroy
メソッドを呼び出すと、ソフト削除が行われます。
await Post.destroy({
where: {
id: 1,
},
});
// UPDATE "posts" SET "deletedAt"=[timestamp] WHERE "deletedAt" IS NULL AND "id" = 1
モデルがパラノイドの場合、本当にハード削除したい場合は、force: true
オプションを使用して強制できます。
await Post.destroy({
where: {
id: 1,
},
force: true,
});
// DELETE FROM "posts" WHERE "id" = 1
上記の例では、静的destroy
メソッド(Post.destroy
)を例として使用しましたが、インスタンスメソッドでもすべて同じように動作します。
const post = await Post.create({ title: 'test' });
console.log(post instanceof Post); // true
await post.destroy(); // Would just set the `deletedAt` flag
await post.destroy({ force: true }); // Would really delete the record
復元
ソフト削除されたレコードを復元するには、静的バージョンとインスタンスバージョンの両方にあるrestore
メソッドを使用できます。
// Example showing the instance `restore` method
// We create a post, soft-delete it and then restore it back
const post = await Post.create({ title: 'test' });
console.log(post instanceof Post); // true
await post.destroy();
console.log('soft-deleted!');
await post.restore();
console.log('restored!');
// Example showing the static `restore` method.
// Restoring every soft-deleted post with more than 100 likes
await Post.restore({
where: {
likes: {
[Op.gt]: 100,
},
},
});
他のクエリでの動作
Sequelizeによって実行されるすべてのクエリは、ソフト削除されたレコードを自動的に無視します(もちろん、rawクエリは除きます)。
これは、たとえば、findAll
メソッドがソフト削除されたレコードを認識せず、削除されていないレコードのみをフェッチすることを意味します。
ソフト削除されたレコードのプライマリキーを指定してfindByPk
を呼び出すだけでも、そのレコードが存在しないかのように、結果はnull
になります。
本当にクエリでソフト削除されたレコードを表示させたい場合は、クエリメソッドにparanoid: false
オプションを渡すことができます。例えば
await Post.findByPk(123); // This will return `null` if the record of id 123 is soft-deleted
await Post.findByPk(123, { paranoid: false }); // This will retrieve the record
await Post.findAll({
where: { foo: 'bar' },
}); // This will not retrieve soft-deleted records
await Post.findAll({
where: { foo: 'bar' },
paranoid: false,
}); // This will also retrieve soft-deleted records