使用sequelize和postgres在多对多关系中创建重复值的问题

时间:2019-07-25 21:05:07

标签: javascript postgresql sequelize.js associations model-associations

我与媒体和标签有很多关系。我正在使用带有此版本sequelize的nodejs

"sequelize": "^5.8.6",
"pg": "^7.11.0",
"pg-hstore": "^2.3.2",

我想接收带有标签列表的新介质,并向每个Postgres表添加create相应的行。

我有这个模型定义:

export default class Media extends Model {
  static init(sequelize) {
    return super.init({
      name: {
        ...
      },
      description: {
        ...
      },
     })     
  static associate(models) {
    this.TagRelation = this.belongsToMany(models.Tag, { through: 
      models.MediaTag, as: 'MediaTags' });
  }
}
export default class MediaTag extends Model {
  static init(sequelize) {
    return super.init({
    }, {
      sequelize,
      timestamps: false,
    });
  }

  static associate(models) {
    this.belongsTo(models.Media, {
      primaryKey: true,
    });
    this.belongsTo(models.Tag, {
      primaryKey: true,
    });
  }
}
export default class Tag extends Model {
  static init(sequelize) {
    return super.init({
      value: {
        allowNull: false,
        type: DataTypes.STRING,
        unique: true,
      },
    });
  }

  static associate(models) {
    this.belongsToMany(models.Media, { through: models.MediaTag, as: 'MediaTags' });
  }

并希望这样做

newMedia = await Media.create({
  ...metadata,
  type: metadata.type.toUpperCase(),
  owner: ctx.user.id,
  MediaTags: tagsValue,
},
{
  include: [{
    association: Media.TagRelation,
    as: 'MediaTags',
    ignoreDuplicates: true,
  }],
});

这仅适用于新标签。如果标签值包含现有标签,则将其解冻

据我了解,这似乎是在创建媒体行,忽略现有标签(我之前创建过标签),但失败了,因为sequlize不会从数据库中的标签中检索tagId。

Executing (default): INSERT INTO "Media" ("id","name","description","likes","dislikes","status","location","owner","type","createdAt","updatedAt") VALUES (DEFAULT,$1,$2,$3,$4,$5,ST_GeomFromGeoJSON($6),$7,$8,$9,$10) RETURNING *;
Executing (default): INSERT INTO "Tags" ("id","value","createdAt","updatedAt") VALUES (DEFAULT,$1,$2,$3) ON CONFLICT DO NOTHING RETURNING *;
Executing (default): INSERT INTO "MediaTags" ("MediumId","TagId") VALUES ($1,$2) ON CONFLICT DO NOTHING RETURNING *;
{ SequelizeDatabaseError: null value in column "TagId" violates not-null constraint
...
 name: 'error',
     length: 214,
     severity: 'ERROR',
     code: '23502',
     detail:
      'Failing row contains (32d5a5c2-e428-4268-a14f-c767b2acc2fb, null).',
     hint: undefined,
     position: undefined,
     internalPosition: undefined,
     internalQuery: undefined,
     where: undefined,
     schema: 'public',
     table: 'MediaTags',
     column: 'TagId',
     dataType: undefined,
     constraint: undefined,
     file: 'execMain.c',
     line: '2042',
     routine: 'ExecConstraints',
     sql:
      'INSERT INTO "MediaTags" ("MediumId","TagId") VALUES ($1,$2) ON CONFLICT DO NOTHING RETURNING *;' },
...

如果我删除ignoreDupliates:

Executing (default): INSERT INTO "Media" ("id","name","description","likes","dislikes","status","location","owner","type","createdAt","updatedAt") VALUES (DEFAULT,$1,$2,$3,$4,$5,ST_GeomFromGeoJSON($6),$7,$8,$9,$10) RETURNING *;
Executing (default): INSERT INTO "Tags" ("id","value","createdAt","updatedAt") VALUES (DEFAULT,$1,$2,$3) RETURNING *;
{ SequelizeUniqueConstraintError: Validation error
...
  name: 'SequelizeUniqueConstraintError',
  errors:
   [ ValidationErrorItem {
       message: 'value must be unique',
       type: 'unique violation',
       path: 'value',
       value: 'tagValue',
       origin: 'DB',
       instance: [Tag],
       validatorKey: 'not_unique',
       validatorName: null,
       validatorArgs: [] } ],

我希望能够创建带有标签列表的新媒体。可以先创建此标签,然后再创建。如果标签不存在,则必须创建。

0 个答案:

没有答案