Sequelize-多对多关联-3个外键

时间:2020-03-05 19:30:06

标签: mysql sequelize.js many-to-many associations

我正在寻找有关在Sequelize模型中正确定义具有3个外键的关联表的帮助:

情况:我正在构建一个电子邮件客户端,此问题的相对模型是:

  • 用户模型(用户记录)
  • 线程模型(每个新电子邮件线程的线程记录)
  • 文件夹模型(默认文件夹的文件夹,例如收件箱,已发送文件夹和自定义文件夹)
  • ThreadFolder 模型(关联到特定a) User 模型到特定b) Thread 模型到特定c)< strong>文件夹模型)

问题:我的问题是关联模型/表(ThreadFolder),我无法为ThreadFolder关联模型中的所有3个表创建关联。


首次尝试我能够与Sequelize创建关联,该关联允许ThreadFolder模型为上述三个模型中的两个创建外键,但不能为所有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 | thread_id:1 | folder_id:1 |成功插入
  2. user_id:1 | thread_id:1 | folder_id:2 |成功插入
  3. user_id:1 | thread_id: 2 | folder_id:1 |插入失败-以下错误...
  4. user_id:2 | thread_id:1 | folder_id:1 |成功插入
  5. user_id:2 | thread_id: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,则会显示以下错误。 / p>

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 | thread_id:1 | folder_id:1 |成功插入
  2. user_id:1 | thread_id:1 | folder_id:2 |成功插入
  3. user_id:1 | thread_id: 2 | folder_id:1 |插入失败-以下错误...
  4. user_id:2 | thread_id:1 | folder_id:1 |成功插入
  5. user_id:2 | thread_id: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中,而一旦我试图表明线程#2的用户#1在文件夹#1中,就会出现上述错误发生。


帮助:

  • 有人可以向我指出正确的方向/显示考虑第三次关联应如何编写关联吗?
  • 是否有其他方法可以一起编写此关联,以便在关联表中考虑所有3个外键?

谢谢您的帮助!

(使用的相对技术:MySQL,MySQL Workbench,Node 12.x,TypeScript,无服务器框架)

编辑:对帖子进行编辑,将第二次尝试作为部分解决方案,经过进一步测试,当将第二个用户添加到关联表ThreadFolder中的相同线程和文件夹时,第一次和第二次尝试均失败。 >

2 个答案:

答案 0 :(得分:1)

查看了create语句后,我认为您已经正确定义了关联[2020-03-07 07:23:21,698] INFO WorkerSourceTask{id=syslog-source-0} Source task finished initialization and start (org.apache.kafka.connect.runtime.WorkerSourceTask:209) [2020-03-07 07:23:31,046] INFO WorkerSourceTask{id=syslog-source-0} Committing offsets (org.apache.kafka.connect.runtime.WorkerSourceTask:416) [2020-03-07 07:23:31,048] INFO WorkerSourceTask{id=syslog-source-0} flushing 0 outstanding messages for offset commit (org.apache.kafka.connect.runtime.WorkerSourceTask:433) 。我认为,您第二次定义关联的尝试是正确的。

插入记录时遇到错误,因为您的主键是thread_foldersthread_id这两个属性的组合键。假设您的folder_id表中已经有thread_folders 1和thread_id 1的记录,那么您不能再插入folder_id 1和thread_id的记录1.

如果删除folder_idthread_id的组合主键,则可以将要插入的记录插入folder_id表中。

希望对您有帮助!

答案 1 :(得分:1)

可行的解决方案最终是第二次尝试的变种:

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'
                ]
            }
        ]
    })

希望这可以帮助其他尝试制作超过2个外键的多外键关联表的人,大概是这种方法应该可以在关联表中使用任意数量的外键。