Из документов: 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