首页 > 解决方案 > 反对 js:无法使用连接表额外属性更新多对多关系。说附加属性无效

问题描述

在 Postgres 上使用 ObjectionJS 而不是 knex,我无法修补与另一个模型具有多对多关系的模型的连接表中的额外属性。即使在关注并阅读和重新阅读文档时,我也无法更新该属性。即使文档列出了我正在做的完全相同的事情。

基本上我有一个候补名单模型,该模型可能有很多用户,在这两者之间有一个连接表,它有一个“排名”属性,就像列表上的索引一样。我正在尝试按照$relatedQuery文档中提供的方法更新此排名属性

尝试了几种查询方法的组合,包括静态和实例;尝试为每个请求再次获取模型,尝试在两个模型上添加关系而不是单个模型(因为我不需要另一个模型来了解关系)但无济于事

为了比较,这是 ObjectionJS 文档中关于额外道具的内容的摘录,可以在此处找到

const linda = await Actor
  .query()
  .findOne({ name: 'Linda Hamilton' });

.
.
.

await linda
  .$relatedQuery('movies')
  .patch({ characterName: 'Florence' })
  .where('movies.name', 'Curvature')

在某处的方法中,我执行以下操作

// At some point above, I do a query().findOne to get the waitlist
// trx is a transaction object
// id is the id of the user I want to update the rank of
        await waitlist
          .$relatedQuery('users', trx)
          .patch({ rank: targetRank })
          .where({ id })

这是一个非常愚蠢的迁移视图

  return knex.schema
    .createTable('users', (table) => {
      table
        .uuid('id')
        .primary()
        .notNullable()
      table.timestamp('createdAt').defaultTo(knex.fn.now())
      table.timestamp('updatedAt').defaultTo(knex.fn.now())
    })
    .createTable('waitlists', (table) => {
      table
        .uuid('id')
        .primary()
        .notNullable()
      table.timestamp('createdAt').defaultTo(knex.fn.now())
      table.timestamp('updatedAt').defaultTo(knex.fn.now())
    })
    .createTable('waitlists_users', (table) => {
      table.uuid('waitlistId')
      table
        .foreign('waitlistId')
        .references('id')
        .inTable('waitlists')
        .onDelete('CASCADE')
      table.uuid('userId')
      table
        .foreign('userId')
        .references('id')
        .inTable('users')
        .onDelete('CASCADE')
      table.primary(['waitlistId', 'userId'])
      table.integer('rank').index()
    })

最后是候补名单模型定义,不提供用户,因为这对该模型应该是完全透明的,它不关心它的排名变化

  static tableName = 'waitlists'

  static jsonSchema = {
    type: 'object',
    required: [],
    properties: {},
  }

  static get relationMappings() {
    const UserModel = require('where/the/model/is/at').default

    return {
      users: {
        relation: ObjectionModel.ManyToManyRelation,
        modelClass: UserModel,
        join: {
          from: 'waitlists.id',
          through: {
            from: 'waitlists_users.waitlistId',
            to: 'waitlists_users.userId',
            extra: ['rank'],
          },
          to: 'users.id',
        },
      },
    }
  }

执行上面那个微小的补丁查询会导致这个

ValidationError: rank: is an invalid additional property
      at Function.createValidationError (node_modules/objection/lib/model/Model.js:397:12)
      at parseValidationError (node_modules/objection/lib/model/AjvValidator.js:189:21)
      at AjvValidator.validate (node_modules/objection/lib/model/AjvValidator.js:78:19)
      at validate (node_modules/objection/lib/model/modelValidate.js:35:20)
      at UserModel.$validate (node_modules/objection/lib/model/Model.js:133:12)
      at setJson (node_modules/objection/lib/model/modelSet.js:28:16)
      at UserModel.$setJson (node_modules/objection/lib/model/Model.js:171:12)
      at Function.fromJson (node_modules/objection/lib/model/Model.js:320:11)
      at Function.ensureModel (node_modules/objection/lib/model/Model.js:630:25)
      at ManyToManyUpdateOperation.onAdd (node_modules/objection/lib/queryBuilder/operations/UpdateOperation.js:22:29)
      at ManyToManyUpdateOperation.onAdd (node_modules/objection/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js:28:23)
      at QueryBuilder.callOperationMethod (node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:345:33)
      at QueryBuilder.addOperationUsingMethod (node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:381:28)
      at QueryBuilder.addOperation (node_modules/objection/lib/queryBuilder/QueryBuilderOperationSupport.js:372:22)
      at writeOperation (node_modules/objection/lib/queryBuilder/QueryBuilder.js:890:12)
      at writeOperation (node_modules/objection/lib/queryBuilder/QueryBuilder.js:1465:5)

注意:我没有采用原始方法,但这只是最后的手段

编辑:为了澄清起见,任何看起来都是假的都是因为它是,我从帖子中删除了大部分包袱(如模型属性和方法),如果需要,请告诉我。用户模式和候补名单模式都已完全开发且功能齐全,它们可以干净地用于 crud。我希望能够在给定等候名单、用户和目标排名的情况下修补连接表行

标签: node.jsormknex.jsobjection.js

解决方案


您的 json 架构必须包含rank属性,或者您需要允许其他属性或一起删除该虚拟架构。

http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.6

  static jsonSchema = {
    type: 'object',
    required: [],
    properties: {},
    additionalProperties: true
  }

推荐阅读