在 Sequelize 中实现软删除(Soft Delete)非常简单,可以通过内置的 paranoid
模式实现。软删除是指不实际删除数据库记录,而是通过标记字段(如 deletedAt
)标识记录已被删除。以下是实现步骤:
1. 启用软删除功能
在定义模型时,设置 paranoid: true
并指定 deletedAt
字段:
javascript
const User = sequelize.define("User", {
// 模型字段定义
name: DataTypes.STRING,
email: DataTypes.STRING,
}, {
paranoid: true, // 启用软删除
deletedAt: "deletedAt", // 指定软删除标记字段(默认是 deletedAt)
});
- 启用后,调用
destroy()
方法不会删除记录,而是设置deletedAt
为当前时间戳。 - 默认查询会自动过滤掉
deletedAt
不为null
的记录。
2. 确保数据库有 deletedAt
字段
执行迁移或同步数据库时,确保表中包含 deletedAt
字段。如果使用迁移工具(如 Sequelize CLI),添加如下字段:
javascript
// 迁移文件(up 方法)
queryInterface.addColumn("Users", "deletedAt", {
type: Sequelize.DATE,
allowNull: true,
});
3. 执行软删除
调用 destroy()
方法进行软删除:
javascript
// 软删除 ID 为 1 的用户
await User.destroy({ where: { id: 1 } });
- 执行后,数据库记录的
deletedAt
会被设置为当前时间戳。 - 默认查询会忽略
deletedAt
不为null
的记录。
4. 查询时包含软删除的记录
如果要查询所有记录(包括已软删除的),需要显式设置 paranoid: false
:
javascript
const users = await User.findAll({
paranoid: false, // 包含软删除的记录
});
5. 恢复软删除的记录
使用 restore()
方法恢复被软删除的记录:
javascript
await User.restore({ where: { id: 1 } });
// 恢复后,deletedAt 会被置为 null
6. 强制删除(硬删除)
如果要物理删除记录(绕过软删除),使用 force: true
:
javascript
await User.destroy({
where: { id: 1 },
force: true, // 强制删除,直接从数据库移除记录
});
完整示例
javascript
// 定义模型
const User = sequelize.define("User", {
name: DataTypes.STRING,
email: DataTypes.STRING,
}, {
paranoid: true,
deletedAt: "deletedAt",
});
// 软删除
await User.destroy({ where: { id: 1 } });
// 查询(默认排除已删除记录)
const activeUsers = await User.findAll();
// 查询包含已删除记录
const allUsers = await User.findAll({ paranoid: false });
// 恢复
await User.restore({ where: { id: 1 } });
// 强制删除
await User.destroy({ where: { id: 1 }, force: true });
注意事项
- 唯一约束冲突:如果字段有唯一约束(如
email
),软删除后恢复可能导致唯一性冲突。解决方案: - 在唯一索引中包含
deletedAt
(索引条件:email + deletedAt
)。 - 自定义逻辑处理(例如,允许
deletedAt
存在时唯一性失效)。 - 关联模型:如果模型有关联关系,需确保关联配置正确(如
onDelete
的级联操作)。
通过上述步骤,即可在 Sequelize 中轻松实现软删除功能。