源起
问题出现:一言爬虫使用Sequelize插入唯一键('content')和先前有重复的数据,会报错。
这里是我的数据库结构,
id是int类型AI自增,content是唯一键并开了索引。
解决尝试——数据库层面
通过模拟并构建SQL命令复现错误,发现问题出在content数据有重复。因为其中只要有一条重复,插入失败,全部都会失败。但id还依然保持自增。
尝试在数据库(mysql)层面解决这一问题,即尝试修改结构使content字段重复不返回失败,并在重复时,不插入新纪录。
查询资料得到如下内容:
- 重复时,更新旧记录
重复时仅更新 ON DUPLICATE KEY UPDATE 后面的字段,其它字段都不更新
INSERT INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES
('lilisss', 100, 'c', '2001-01-02 00:00:00', 2)
ON DUPLICATE KEY UPDATE name = CONCAT(values(name), '_'), age = values(age) + 20;
重复时用新记录覆盖旧记录
INSERT INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES
('lili', 19, 'c', '2001-01-02 00:00:00', 2)
ON DUPLICATE KEY UPDATE name = values(name), age = values(age), sex = values(sex), birthday = values(birthday), class = values (class);
- 重复时,不插入新纪录
INSERT IGNORE INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES ('lili', 19, 'm', '2001-01-02 00:00:00', 2);
重复时删除重建,删除原语句,插入新语句
REPLACE INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES
('lilissssss', 19, 's', '2001-01-02 00:00:00', 2);
- 重复时,删除旧记录,插入新记录
REPLACE INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES ('lilissssss', 19, 's', '2001-01-02 00:00:00', 2);
但是我总不能使用了Sequelize还使用原生SQL吧,于是开始寻找Sequelize层面的解决方案。
解决尝试——Sequelize层面
因为我是批量新增数据,故使用方法Model.bulkCreate([…object])
例如:
let params = [{"name": "张三", "age": 21},{"name": "小李", "age": 20}];
let data = await model.bulkCreate(params);
以上代码便可以批量在数据库中插入数据,但是默认不会过滤掉重复的内容,比如我这次的数组里已经有张三这个人,下一次我插入数据库中就应该只插入小李而不会再次存入张三。
与此同时,我们应该在定义数据模型的时候在这两个字段加上唯一索引,不然是无效的。
例如:
name: {
type: DataTypes.STRING(128),
unique: true, //唯一
allowNull: false, //将 allowNull 设置为 false 将为该列添加 NOT NULL
},
age: {
type: DataTypes.INTEGER,
unique: true, //唯一
allowNull: false, //将 allowNull 设置为 false 将为该列添加 NOT NULL
},
于是乎:
let params = [{"name": "张三", "age": 21},{"name": "小李", "age": 20}];
let data = await model.bulkCreate(params,{
updateOnDuplicate:['name','age']
});
这样就可以完美插入数据啦!!!
资料查询清单:
总有些代码是看不懂的 :)
希恩 2022-08-02
我们同学也说这篇逻辑和表达不好,我再优化一下~q(≧▽≦q)
hissin' 2022-08-02 回复 @希恩