Sequelize - ассоциация многих ко многим - 3 иностранных ключа - PullRequest
2 голосов
/ 05 марта 2020

Мне нужна помощь в правильном определении таблицы ассоциации с 3 внешними ключами в модели Sequelize:

Ситуация: Я создаю почтовый клиент, соответствующие модели К этому вопросу относятся:

  • Пользователь Модель (записи пользователя)
  • Тема Модель (записи потока для каждой новой электронной почты)
  • Папка Модель (папки для папок по умолчанию, например папки «Входящие», «Отправленные» и др. c и пользовательских папок)
  • ThreadFolder Модель (ассоциация, связывающая Специф. c a) Пользователь Модель, для спецификации c b) Нить Модель, для спецификации c c) Папка Модель )

Проблема: Моя проблема связана с моделью / таблицей ассоциации (ThreadFolder), я не могу создать ассоциацию для всех 3 таблиц в модели ассоциации ThreadFolder.


Первая попытка Я могу создать ассоциацию с Sequelize, которая позволяет модели ThreadFolder создавать внешние ключи для 2 из трех моделей выше, но не для всех 3. Здесь это ассоциация для этого:

Thread.belongsToMany(Folder, { through: ThreadFolder, foreignKey: 'thread_id', otherKey: 'folder_id' })
Folder.belongsToMany(Thread, { through: ThreadFolder, foreignKey: 'folder_id', otherKey: 'thread_id' })

SQL Попытки ввода:

  1. user_id: 1 | идентификатор_потока: 1 | folder_id: 1 | Успешная вставка
  2. user_id: 1 | идентификатор_потока: 1 | folder_id: 2 | Успешная вставка
  3. user_id: 1 | идентификатор_потока: 2 | folder_id: 1 | Ошибка вставки - ошибка ниже ...
  4. user_id: 2 | идентификатор_потока: 1 | folder_id: 1 | Успешная вставка
  5. user_id: 2 | идентификатор_потока: 1 | folder_id: 2 | Успешная вставка

Ошибка первой попытки:

Executing:
INSERT INTO `iwantmail-core`.`thread_folders` (`user_id`, `deleted`, `archived`, `created_at`, `updated_at`, `thread_id`, `folder_id`) VALUES ('1', '0', '0', '2020-03-05 23:34:16', '2020-03-05 23:34:16', '30', '1');

Operation failed: There was an error while applying the SQL script to the database.
ERROR 1062: 1062: Duplicate entry '30-1' for key 'PRIMARY'
SQL Statement:
INSERT INTO `iwantmail-core`.`thread_folders` (`user_id`, `deleted`, `archived`, `created_at`, `updated_at`, `thread_id`, `folder_id`) VALUES ('1', '0', '0', '2020-03-05 23:34:16', '2020-03-05 23:34:16', '30', '1')

Вторая попытка Я могу указать связь, как показано ниже, чтобы я мог добавлять записи с разными user_id и folder_id, однако, если я использую другой thread_id, я получаю сообщение об ошибке, показанное ниже.

Folder.hasMany(ThreadFolder, { foreignKey: 'folder_id' })
ThreadFolder.belongsTo(Folder, { foreignKey: 'folder_id' })
Thread.belongsToMany(Folder, { through: ThreadFolder })

Thread.hasMany(ThreadFolder, { foreignKey: 'thread_id' })
ThreadFolder.belongsTo(Thread, { foreignKey: 'thread_id' })

User.hasMany(ThreadFolder, { foreignKey: 'user_id' })
ThreadFolder.belongsTo(User, { foreignKey: 'user_id' })
Folder.belongsToMany(User, { through: ThreadFolder })

SQL Попытки ввода:

  1. user_id: 1 | идентификатор_потока: 1 | folder_id: 1 | Успешная вставка
  2. user_id: 1 | идентификатор_потока: 1 | folder_id: 2 | Успешная вставка
  3. user_id: 1 | идентификатор_потока: 2 | folder_id: 1 | Ошибка вставки - ошибка ниже ...
  4. user_id: 2 | идентификатор_потока: 1 | folder_id: 1 | Успешная вставка
  5. user_id: 2 | идентификатор_потока: 1 | folder_id: 2 | Успешная вставка

Ошибка второй попытки

Operation failed: There was an error while applying the SQL script to the database.
ERROR 1062: 1062: Duplicate entry '1-1' for key 'PRIMARY'
SQL Statement:
INSERT INTO `mail-core`.`thread_folders` (`user_id`, `thread_id`, `folder_id`) VALUES ('1', '2', '1')

Обратите внимание, что я в основном пытаюсь указать, что пользователь # 1 из потока # 1 в папке # 1, и как только я пытаюсь указать, что пользователь # 1 из потока № 2 находится в папке # 1, возникает вышеуказанная ошибка.


Справка:

  • Может ли кто-нибудь указать мне правильное направление / показать, как должна быть написана ассоциация, чтобы учесть 3-ю ассоциацию?
  • Есть ли другой способ написать эту ассоциацию все вместе, чтобы все 3 внешних ключа учитываются в таблице ассоциации?

Заранее благодарен за любую помощь / помощь!

(Используемые относительные технологии: MySQL, MySQL Workbench , Node 12.x, TypeScript, Serverless Framework)

РЕДАКТИРОВАТЬ: внесены изменения в сообщение, 2-я попытка была представлена ​​как частичное решение, после дальнейшего тестирования, 1-я и 2-я попытки завершаются неудачно, когда добавляется 2-й пользователь в ту же нить и фол der в таблице ассоциации ThreadFolder.

Ответы [ 2 ]

1 голос
/ 07 марта 2020

После просмотра ваших утверждений create я думаю, что вы правильно определили ассоциации thread_folders. На мой взгляд, ваша вторая попытка определения ассоциации верна.

Вы получаете ошибку при вставке записей, потому что ваш первичный ключ - это комбинированный ключ двух атрибутов, а именно thread_id и folder_id. Допустим, в вашей таблице thread_folders уже есть запись для thread_id 1 и folder_id 1, тогда вы не можете вставить другую запись с thread_id 1 и folder_id 1.

Если вы удалите объединенный первичный ключ thread_id и folder_id, после чего вы сможете вставить записи, которые вы хотите вставить в таблицу thread_folders.

Надеюсь, это поможет!

0 голосов
/ 09 марта 2020

Рабочее решение оказалось дисперсией второй попытки:

User.hasMany(ThreadFolder, { foreignKey: 'user_id' })
ThreadFolder.belongsTo(User, { foreignKey: 'user_id' })

Folder.hasMany(ThreadFolder, { foreignKey: 'folder_id' })
ThreadFolder.belongsTo(Folder, { foreignKey: 'folder_id' })

Thread.hasMany(ThreadFolder, { foreignKey: 'thread_id' })
ThreadFolder.belongsTo(Thread, { foreignKey: 'thread_id' })

Большинство моих вызовов модели (в зависимости от того, как они были написаны ранее) в конечном итоге изменится, чтобы сначала начать с таблицы ассоциации, например

 ThreadFolder.findAll({
        where: {
            user_id: 1,
            folder_id: 1,
        },
        include: [
            {
                model: Thread,
                include: [
                    'recipient',
                    'sender'
                ]
            }
        ]
    })

Надеюсь, что это поможет другим, которые пытались создать таблицу сопоставления с несколькими внешними ключами за пределами двух внешних ключей, предположительно, этот подход должен работать с любым количеством внешних ключей в таблице сопоставления.

...