写这段代码是为了理解M:N关系。想法很简单,PK是由其他表中的2个FK组成的。
检查MySQL表是正常的,约束是正常的,唯一的问题是,关系的重复的Add on PK没有包括在内(按预期工作),但也没有抛出错误。
代码如下:
const Sequelize = require('sequelize');
const Model = Sequelize.Model
const path = 'mysql://myuser:mypass@localhost:3306/dbtest';
const sequelize = new Sequelize(path, {
logging: false
});
class PostTag extends Model { }
/*
PostTag.init({
postId: {
type: Sequelize.INTEGER,
primaryKey: true,
unique: "postTagConstraint"
},
tagId: {
type: Sequelize.INTEGER,
primaryKey: true,
unique: "postTagConstraint"
}
}, { sequelize, modelName: 'post_tag' });
*/
class Post extends Model { }
Post.init({
title: Sequelize.STRING,
text: Sequelize.STRING
}, { sequelize, modelName: 'post' });
class Tag extends Model { }
Tag.init({
name: Sequelize.STRING,
status: Sequelize.STRING
}, { sequelize, modelName: 'tag' });
/*
Post.belongsToMany(Tag, {
through: {
model: PostTag
},
foreignKey: 'postId'
});
Tag.belongsToMany(Post, {
through: {
model: PostTag
},
foreignKey: 'tagId'
});
*/
Post.belongsToMany(Tag, { through : 'PostTag' });
Tag.belongsToMany(Post, { through : 'PostTag' });
async function Add() {
let tag1 = await Tag.create({ name: 'Nice', status: 'Funcional' });
let tag2 = await Tag.create({ name: 'Bad', status: 'Not working' });
//console.log(tag1.name);
//console.log(tag2.name);
let post1 = await Post.create({ title: 'A very nice post', text: 'This is post1' });
let post2 = await Post.create({ title: 'Toxic post', text: 'This is post2' });
//console.log(`${post1.title} - ${post1.text}`);
//console.log(`${post2.title} - ${post2.text}`);
await post1.addTags([tag1, tag2]);
await post2.addTags([tag2]);
let res1 = await Post.findAll({ where: { id: 1 }, include: [Tag] });
res1.forEach(p => {
console.log(`${p.title} - ${p.text}`)
p.tags.forEach(t => console.log(`${t.name} - ${t.status}`));
});
// No error being throw on duplicated
await post2.addTags([tag1, tag2]);
}
sequelize.sync({ force: true }).then(() => {
Add();
console.log('It shall be one!');
});正如你所看到的,我用一个有效的和一个无效的强制添加了另一个,有效的一个被插入,复制一个被忽略。为什么?
发布于 2019-06-28 11:58:00
我认为如果你分析生成的SQL,这将是非常清楚的。
.addTags做的是对目标数据的外键值进行UPDATE操作。
因此,它将简单地覆盖以前的外键值。
假设你有Post (id1)和Tag (id1), Tag(id2)。
如果先调用Post.addTags([tag1])然后调用Post.addTags([tag1, tag2]),
结果将是Post (id1)和Tag (id1, post_id1), Tag(id2, post_id1)。
因此,如果您想禁止具有相同密钥的项,那么您应该在您的foreign key上设置unique constraint。
下面是来自sequelize manual的示例代码。
// Creating two objects with the same value will throw an error. The unique property can be either a
// boolean, or a string. If you provide the same string for multiple columns, they will form a
// composite unique key.
uniqueOne: { type: Sequelize.STRING, unique: 'compositeIndex' },
uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex' },在你的例子中,它看起来像这样,
tag_id: {
type: DataTypes.INTEGER,
references: {
model: 'Post',
key: 'id',
},
unique: 'constraint name'
}因为您正在对tag_id设置唯一约束。
https://stackoverflow.com/questions/56792378
复制相似问题