Node Sequelize Postgres - BulkCreate 忽略自定义字段的重复值
Node Sequelize Postgres - BulkCreate ignore duplicate values for custom fields
目标: 我有来自另一项服务的 objects 列表,我想将其保留在我自己的 Postgres 数据存储区中。来自此其他服务的数据 returns JSON,但不包含任何 ID。
当前结果:
- 当我第一次 运行 bulkCreate 时,它成功地将数据同步到我的数据库(参见下面的示例代码)
- 当我从其他服务获取新的批次(即检查更新)并再次调用 bulkCreate 时,new 主题被插入数据库中的每一行,即使标题已经存在
预期结果
- 当我第一次 运行 bulkCreate 时,它成功地将数据同步到我的数据库(参见下面的示例代码)
- 当我从其他服务获取新的批次(即检查更新)并再次调用 bulkCreate 时,只有标题在数据库中找不到的主题被插入,其余的有他们的 'count' 属性 已更新。
Topic.js
const database = require('../../shared/database'); // shared db connection. This works
const {DataTypes, Model} = require('sequelize');
class Topic extends Model { }
Topic.init({
topicId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
defaultValue: undefined,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
count: {
type: DataTypes.INTEGER,
allowNull: true,
},
}, {
sequelize: database,
});
module.exports = Topic;
SyncAPI.js(第一个 运行)- 按预期工作
const url = 'https://....'; // the remote service
const topics = await this.http.get(url); // simple example of getting the new data
// [{ 'title': 'Leadership', 'count': 214 },
// { 'title': 'Management', 'count': 51 }]
await Topic.bulkCreate(topics);
// [{ 'topicId': 1, 'title': 'Leadership', 'count': 214 },
// { 'topicId': 2, 'title': 'Management', 'count': 51 }]
SyncAPI.js(第 2 个 运行)- 创建重复项
const url = 'https://....'; // the remote service
const topics = await this.http.get(url); // note how the title is the same with updated counts
// [{ 'title': 'Leadership', 'count': 226 },
// { 'title': 'Management', 'count': 54 }]
await Topic.bulkCreate(topics); // the old, inserted topics remaining, with new entries appended
// [{ 'topicId': 1, 'title': 'Leadership', 'count': 214 },
// { 'topicId': 2, 'title': 'Management', 'count': 51 },
// [{ 'topicId': 3, 'title': 'Leadership', 'count': 226 },
// { 'topicId': 4, 'title': 'Management', 'count': 54 }
我在这里看到了续集文档 (https://sequelize.org/master/class/lib/model.js~Model.html#static-method-bulkCreate),它说我可以指定一个 'ignoreDuplicates' 选项,但它只能通过比较主键来工作(“忽略主键的重复值”)。
我正在 bulkCreate() 方法中寻找某种方法来使用我的自定义键 'title' 指定 'ignoreDuplicates',然后使用 'updateOnDuplicate' 更新计数。
我最终的解决方案是实际获取标题并将其转换为散列,然后将其作为 'topic_uid' 作为 UUID 存储在我的数据库中。
即使我参加聚会有点晚,它也可能对某人有所帮助 :)
您可以在模型级别定义自己的“唯一”索引(甚至可以是复合索引),这将用于检查唯一性...
const database = require('../../shared/database'); // shared db connection. This works
const {DataTypes, Model} = require('sequelize');
class Topic extends Model { }
Topic.init({
topicId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
defaultValue: undefined,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
count: {
type: DataTypes.INTEGER,
allowNull: true,
},
}, {
sequelize: database,
indexes: [{
unique: true,
fields: ['title'] // you can use multiple columns as well here
}]
});
module.exports = Topic;
现在,当您 运行 此命令时,它不会创建任何重复项并简单地忽略它们...
await Topic.bulkCreate(topics, {ignoreDuplicates: true);
目标: 我有来自另一项服务的 objects 列表,我想将其保留在我自己的 Postgres 数据存储区中。来自此其他服务的数据 returns JSON,但不包含任何 ID。
当前结果:
- 当我第一次 运行 bulkCreate 时,它成功地将数据同步到我的数据库(参见下面的示例代码)
- 当我从其他服务获取新的批次(即检查更新)并再次调用 bulkCreate 时,new 主题被插入数据库中的每一行,即使标题已经存在
预期结果
- 当我第一次 运行 bulkCreate 时,它成功地将数据同步到我的数据库(参见下面的示例代码)
- 当我从其他服务获取新的批次(即检查更新)并再次调用 bulkCreate 时,只有标题在数据库中找不到的主题被插入,其余的有他们的 'count' 属性 已更新。
Topic.js
const database = require('../../shared/database'); // shared db connection. This works
const {DataTypes, Model} = require('sequelize');
class Topic extends Model { }
Topic.init({
topicId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
defaultValue: undefined,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
count: {
type: DataTypes.INTEGER,
allowNull: true,
},
}, {
sequelize: database,
});
module.exports = Topic;
SyncAPI.js(第一个 运行)- 按预期工作
const url = 'https://....'; // the remote service
const topics = await this.http.get(url); // simple example of getting the new data
// [{ 'title': 'Leadership', 'count': 214 },
// { 'title': 'Management', 'count': 51 }]
await Topic.bulkCreate(topics);
// [{ 'topicId': 1, 'title': 'Leadership', 'count': 214 },
// { 'topicId': 2, 'title': 'Management', 'count': 51 }]
SyncAPI.js(第 2 个 运行)- 创建重复项
const url = 'https://....'; // the remote service
const topics = await this.http.get(url); // note how the title is the same with updated counts
// [{ 'title': 'Leadership', 'count': 226 },
// { 'title': 'Management', 'count': 54 }]
await Topic.bulkCreate(topics); // the old, inserted topics remaining, with new entries appended
// [{ 'topicId': 1, 'title': 'Leadership', 'count': 214 },
// { 'topicId': 2, 'title': 'Management', 'count': 51 },
// [{ 'topicId': 3, 'title': 'Leadership', 'count': 226 },
// { 'topicId': 4, 'title': 'Management', 'count': 54 }
我在这里看到了续集文档 (https://sequelize.org/master/class/lib/model.js~Model.html#static-method-bulkCreate),它说我可以指定一个 'ignoreDuplicates' 选项,但它只能通过比较主键来工作(“忽略主键的重复值”)。
我正在 bulkCreate() 方法中寻找某种方法来使用我的自定义键 'title' 指定 'ignoreDuplicates',然后使用 'updateOnDuplicate' 更新计数。
我最终的解决方案是实际获取标题并将其转换为散列,然后将其作为 'topic_uid' 作为 UUID 存储在我的数据库中。
即使我参加聚会有点晚,它也可能对某人有所帮助 :)
您可以在模型级别定义自己的“唯一”索引(甚至可以是复合索引),这将用于检查唯一性...
const database = require('../../shared/database'); // shared db connection. This works
const {DataTypes, Model} = require('sequelize');
class Topic extends Model { }
Topic.init({
topicId: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
defaultValue: undefined,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
count: {
type: DataTypes.INTEGER,
allowNull: true,
},
}, {
sequelize: database,
indexes: [{
unique: true,
fields: ['title'] // you can use multiple columns as well here
}]
});
module.exports = Topic;
现在,当您 运行 此命令时,它不会创建任何重复项并简单地忽略它们...
await Topic.bulkCreate(topics, {ignoreDuplicates: true);