Как использовать данные JSONB в виртуальном типе данных? - PullRequest
0 голосов
/ 23 января 2020

Я определяю следующий объект в моей модели:

result: {
  type: DataTypes.JSONB,
  defaultValue: {},
  jsonSchema: {
    schema: {
      type: 'object'
    }
  }
}

Данные json, хранящиеся в этом объекте, выглядят так:

"result": {
    "score": {
        "scaled": 1,
        "raw": 8,
        "min": 7,
        "max": 10
    },
    "success": true,
    "completion": true,
    "duration": "2H30M"
}

Теперь я пытаюсь создать виртуальный поле со значением off успех. Я пытался сделать это, но безуспешно.

result_success: {
  type: DataTypes.VIRTUAL,
  get () {
    return this.getDataValue('result').success;
  }
},

Но это не возвращается, когда я делаю запрос через эту модель.

1 Ответ

1 голос
/ 13 февраля 2020

Это работает для меня. Вот пример:

index.ts:

import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
import assert from 'assert';

class SomeEntity extends Model {
  public id!: number;
  public result!: any;
  public result_success!: boolean;
}
SomeEntity.init(
  {
    result: {
      type: DataTypes.JSONB,
      defaultValue: {},
    },
    result_success: {
      type: DataTypes.VIRTUAL,
      get(this: SomeEntity) {
        return this.getDataValue('result').success;
      },
    },
  },
  { sequelize, modelName: 'SomeEntities' },
);

(async function test() {
  try {
    await sequelize.sync({ force: true });
    // seed
    const entity = await SomeEntity.create({
      result: {
        score: { scaled: 1, raw: 8, min: 7, max: 10 },
        success: true,
        completion: true,
        duration: '2H30M',
      },
    });
    assert(entity.result_success, 'The value of the virtual field result_success should be truthy');
    console.log('entity.result_success: ', entity.result_success);
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

После выполнения вышеуказанного кода, проверьте записи данных в базе данных:

node-sequelize-examples=# select * from "SomeEntities";
 id |                                                      result
----+-------------------------------------------------------------------------------------------------------------------
  1 | {"score": {"max": 10, "min": 7, "raw": 8, "scaled": 1}, "success": true, "duration": "2H30M", "completion": true}
(1 row)

И распечатанный журнал виртуальное поле entity.result_success возвращает true, как и ожидалось:

{ POSTGRES_HOST: '127.0.0.1',
  POSTGRES_PORT: '5430',
  POSTGRES_PASSWORD: 'testpass',
  POSTGRES_USER: 'testuser',
  POSTGRES_DB: 'node-sequelize-examples' }
Executing (default): DROP TABLE IF EXISTS "SomeEntities" CASCADE;
Executing (default): DROP TABLE IF EXISTS "SomeEntities" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "SomeEntities" ("id"   SERIAL , "result" JSONB DEFAULT '{}', 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 = 'SomeEntities' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "SomeEntities" ("id","result") VALUES (DEFAULT,$1) RETURNING *;
entity.result_success:  true

исходный код: https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/stackoverflow/59877140

...