首页 > 解决方案 > Node Sequelize Postgres - BulkCreate 忽略自定义字段的重复值

问题描述

目标:我有一个来自另一个服务的对象列表,我想保留在我自己的 Postgres 数据存储中。来自此其他服务的数据返回 JSON,但不包含任何 ID。

目前的结果:

预期结果

主题.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(第二次运行)- 创建重复项

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' 来更新计数。

标签: node.jspostgresqlsequelize.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, 
  indexes: [{
             unique: true,
             fields: ['title'] // you can use multiple columns as well here
           }]
});

module.exports = Topic;

现在,当您运行此命令时,它不会创建任何重复项并简单地忽略它们...

await Topic.bulkCreate(topics, {ignoreDuplicates: true);

推荐阅读