Я совсем недавно работал над хобби -проектом: приложение для контроля доступа, основанное на роле, где мне нужно было реализовать Каскад удалить
в некоторых моделях. Например, пользовательская модель была Роли
Атрибут, который был массивом ObjectId
Сделай образец для подражания:
const mongoose = require("mongoose"); const UserSchema = new mongoose.Schema({ username: { type: String, unique: true, required: true }, password: { type: String, required: true }, roles: [ { type: mongoose.Schema.Types.ObjectId, required: true, ref: "Role" } ] });
Роли динамически создаются и назначены пользователям. Проблема, с которой я столкнулся, заключается в том, что когда роль удаляется, это ObjectId
Ссылки в модели пользователя также не были удалены, поэтому становятся осиротевшие , следовательно, нарушение ссылочной целостности.
Чтобы предотвратить это, мне нужно было реализовать Каскад удалить
Анкет В SQL это так же просто, как добавление На удалении каскада
ссылочное действие при создании вашего users_roles
стол как так:
CREATE TABLE users_roles ( user_id int unsigned not null, role_id int unsigned not null, PRIMARY KEY (user_id, role_id), FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE, FOREIGN KEY(role_id) REFERENCES roles (id) ON DELETE CASCADE );
Но я использовал mongodb и Монгуз ODM. Как я должен был сделать это? Я смог решить это, используя Mongoose Middlewares Анкет В соответствии с их документацией, Mongoose Middlewares или крючки – это функции, которые передаются управляющим во время выполнения асинхронных функций. Пост
промежуточное программное обеспечение или крюк, в частности, это именно то, что мне нужно, так как это позволило бы мне выполнить некоторые действия сразу после завершения операции базы данных:
const mongoose = require("mongoose"); const User = require("./user"); const RoleSchema = new mongoose.Schema({ title: { type: String, required: true } }); RoleSchema.post("remove", document => { const roleId = document._id; User.find({ roles: { $in: [roleId] } }).then(users => { Promise.all( users.map(user => User.findOneAndUpdate( user._id, { $pull: { roles: roleId } }, { new: true } ) ) ); }); }); module.exports = mongoose.model("Role", RoleSchema);
Позвольте мне кратко описать код выше. Сразу после удаления определенной роли я нахожу всех пользователей, которые имеют эту идентификацию этой роли в их массиве ролей, используя Mongodb $ в
Оператор (Mongoose позволяет использовать нативные операторы MongoDB в ваших запросах).
.... User.find({ roles: { $in: [roleId] } })
Затем для каждого пользователя, который удовлетворяет критериям, другого оператора, $ pull
Оператор используется для «вытягивания» или удаления этой конкретной идентификации роли из их массива ролей.
.... User.findOneAndUpdate( user._id, { $pull: { roles: roleId } }, { new: true } )
Это подход, который я использовал для реализации Каскад удалить
в мангузе, чтобы обеспечить референциальную целостность. Я хотел бы услышать о других подходах, которые вы можете использовать, чтобы решить аналогичную проблему в мангузе.
Счастливого кодирования, все!
Оригинал: “https://dev.to/kwabenberko/implementing-sql–like-cascades-in-mongoose-bap”