Рубрики
Без рубрики

Внедрение каскадов SQL-подобных в монгузе

Я совсем недавно работал над хобби -проектом: приложение для контроля доступа, основанное на роли … Tagged с производительностью, JavaScript, Node, MongoDB.

Я совсем недавно работал над хобби -проектом: приложение для контроля доступа, основанное на роле, где мне нужно было реализовать Каскад удалить в некоторых моделях. Например, пользовательская модель была Роли Атрибут, который был массивом 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”