Sequelize Postgres - 如何使用 ON CONFLICT 来实现独特的?

Posted

技术标签:

【中文标题】Sequelize Postgres - 如何使用 ON CONFLICT 来实现独特的?【英文标题】:Sequelize Postgres - How to use ON CONFLICT for unique? 【发布时间】:2019-11-22 08:42:09 【问题描述】:

我正在将sequelize 实现到我的 NodeJS 应用程序中。在此之前,我使用了一个书面 INSERT 查询,该查询使用 ON CONFLICT (field) DO NOTHING 来处理不插入值需要唯一的记录。

const sql = 'INSERT INTO communications (firstname, lastname, age, department, campus, state, message_uuid) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (message_uuid) DO NOTHING';

const values = [val.firstName, val.lastName, val.age, val.department, val.campus, val.state, message_uuid];

sequelize 中是否对此提供支持,我可以在模型中定义相同的东西?或者也许是更好的处理方式?

本质上,如果表中已存在一条记录,该记录位于 message_uuid = 123 列中,而另一条记录尝试插入具有相同值的记录,则会忽略它并且不执行任何操作。

【问题讨论】:

你有没有想过这个问题?我想知道如何做同样的事情。 【参考方案1】:

作为Model.create 的第二个参数,您可以提供onConflict 属性,请阅读文档

【讨论】:

这里是 sequelize 源代码中“onConflict”的 github 搜索结果:github.com/… 不过,这里有类似的东西存在的证明:github.com/sequelize/sequelize/blob/master/lib/dialects/…【参考方案2】:

您可以将public static bulkCreate(records: Array, options: Object): Promise<Array> 方法与options.ignoreDuplicates 一起使用。

忽略主键的重复值? (MSSQL 或 Postgres

此外,为模型上的message_uuid 字段添加unique 约束也很重要。这样查询将使用 Postgres 的ON CONFLICT DO NOTHING 子句。

例如,"sequelize": "^5.21.3"postgres:9.6

import  sequelize  from '../../db';
import  Model, DataTypes  from 'sequelize';

class Communication extends Model 
Communication.init(
  
    firstname: DataTypes.STRING,
    lastname: DataTypes.STRING,
    age: DataTypes.INTEGER,
    message_uuid: 
      type: DataTypes.INTEGER,
      unique: true,
    ,
  ,
   sequelize, tableName: 'communications' ,
);

(async function test() 
  try 
    await sequelize.sync( force: true );
    // seed
    await Communication.create( firstname: 'teresa', lastname: 'teng', age: 32, message_uuid: 123 );
    // test
    await Communication.bulkCreate([ firstname: 'teresa', lastname: 'teng', age: 32, message_uuid: 123 ], 
      ignoreDuplicates: true,
    );
   catch (error) 
    console.log(error);
   finally 
    await sequelize.close();
  
)();

执行结果:

Executing (default): DROP TABLE IF EXISTS "communications" CASCADE;
Executing (default): DROP TABLE IF EXISTS "communications" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "communications" ("id"   SERIAL , "firstname" VARCHAR(255), "lastname" VARCHAR(255), "age" INTEGER, "message_uuid" INTEGER UNIQUE, PRIMARY KEY ("id"));
Executing (default): SELECT i.relname AS name, ix.indisprimary AS primary, ix.indisunique AS unique, ix.indkey AS indkey, array_agg(a.attnum) as column_indexes, array_agg(a.attname) AS column_names, pg_get_indexdef(ix.indexrelid) AS definition FROM pg_class t, pg_class i, pg_index ix, pg_attribute a WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid AND t.relkind = 'r' and t.relname = 'communications' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "communications" ("id","firstname","lastname","age","message_uuid") VALUES (DEFAULT,$1,$2,$3,$4) RETURNING *;
Executing (default): INSERT INTO "communications" ("id","firstname","lastname","age","message_uuid") VALUES (DEFAULT,'teresa','teng',32,123) ON CONFLICT DO NOTHING RETURNING *;

查看数据库,果然只有一行。

node-sequelize-examples=# select * from communications;
 id | firstname | lastname | age | message_uuid 
----+-----------+----------+-----+--------------
  1 | teresa    | teng     |  32 |          123
(1 row)

【讨论】:

以上是关于Sequelize Postgres - 如何使用 ON CONFLICT 来实现独特的?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Sequelize Postgres 中使用小写函数

Sequelize Postgres - 如何使用 ON CONFLICT 来实现独特的?

用户如何使用 sequelize postgres nodejs 互相喜欢和不同?

如何在 NestJs 框架中使用 postgres 和 sequelize 正确定义 DTO 对象

Sequelize w/Postgres 测试异步错误

Node.js Sequelize UUID 主键 + Postgres