модель секвестирования исключает подполе в поле jsonb - PullRequest
0 голосов
/ 06 апреля 2020

У меня есть таблица postgresql, структурированная с полем jsonb с именем external_data: external_data: {a: 1, b:2, c:3}

Я знаю, что в последовательных определениях модели вы можете исключить поле, включив в свойства параметров параметр defaultScope, подобный этому :

{defaultScope: {attributes: { exclude: ['external_data'] }}

Когда я делаю это, чтобы исключить все поле, оно работает, то есть external_data не отображается в возвращаемых результатах. Однако я хотел бы исключить указанное подполе c. Я пробовал exclude: ['external_data.b'], но, похоже, это не сработало.

Позволяет ли sequelize исключать подполя в полях jsonb? И если да, то каков правильный формат атрибута exclude для этого?

1 Ответ

0 голосов
/ 13 апреля 2020

Из документов: https://sequelize.org/v5/manual/scopes.html

Области определены в определении модели и могут быть объектами поиска или функциями, возвращающими объекты поиска - за исключением области действия по умолчанию, который может быть только объектом

Итак, вы можете определить область действия через функцию, которая возвращает объекты поиска, чтобы вы могли реализовать сложную область действия.

Например,

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

class TableA extends Model {}
TableA.init(
  {
    external_data: DataTypes.JSONB,
  },
  {
    sequelize,
    modelName: 'table_a',
    defaultScope: {
      attributes: { exclude: ['external_data'] },
    },
    scopes: {
      exclude(subField) {
        return {
          where: {
            external_data: {
              [subField]: {
                [Op.eq]: null,
              },
            },
          },
        };
      },
    },
  },
);

(async function test() {
  try {
    // create tables
    await sequelize.sync({ force: true });
    // seed
    await TableA.bulkCreate([
      { external_data: { a: 1, b: 2, c: 3 } },
      { external_data: { a: 10, c: 30 } },
      { external_data: { a: 100 } },
    ]);
    // test
    // test case 1: exclude subfield "b"
    const result1 = await TableA.scope({ method: ['exclude', 'b'] }).findAll({ raw: true });
    console.log('result1:', result1);
    // test case 2: exclude subfield "c"
    const result2 = await TableA.scope({ method: ['exclude', 'c'] }).findAll({ raw: true });
    console.log('result2:', result2);
  } catch (error) {
    console.log(error);
  } finally {
    await sequelize.close();
  }
})();

Результаты выполнения:

Executing (default): DROP TABLE IF EXISTS "table_a" CASCADE;
Executing (default): DROP TABLE IF EXISTS "table_a" CASCADE;
Executing (default): CREATE TABLE IF NOT EXISTS "table_a" ("id"   SERIAL , "external_data" JSONB, 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 = 'table_a' GROUP BY i.relname, ix.indexrelid, ix.indisprimary, ix.indisunique, ix.indkey ORDER BY i.relname;
Executing (default): INSERT INTO "table_a" ("id","external_data") VALUES (DEFAULT,'{"a":1,"b":2,"c":3}'),(DEFAULT,'{"a":10,"c":30}'),(DEFAULT,'{"a":100}') RETURNING *;
Executing (default): SELECT "id", "external_data" FROM "table_a" AS "table_a" WHERE ("table_a"."external_data"#>>'{b}') IS NULL;
result1: [ { id: 2, external_data: { a: 10, c: 30 } },
  { id: 3, external_data: { a: 100 } } ]
Executing (default): SELECT "id", "external_data" FROM "table_a" AS "table_a" WHERE ("table_a"."external_data"#>>'{c}') IS NULL;
result2: [ { id: 3, external_data: { a: 100 } } ]

проверка базы данных:

node-sequelize-examples=# select * from "table_a";
 id |      external_data
----+--------------------------
  1 | {"a": 1, "b": 2, "c": 3}
  2 | {"a": 10, "c": 30}
  3 | {"a": 100}
(3 rows)

Версии зависимостей: "sequelize": "^5.21.3", postgres:9.6

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

...