sequelize-mv-support v4.1.2
Sequelize with Views & Materialized Views
This package adds support for Views and Materialized Views in Sequelize.
NOTE: Currently it's only supported in PostgreSQL.
Motivation
We're heavy users of views and materialized views, but we use Sequelize a lot for bootstrapping and testing database schema. This module was based on Abel Osorio's sequelize-views-support. In addition to the view support in Abel's module, this module adds support for both views and materialized views to Sequelize, as well as properly exporting typescript declarations. I also added integration tests for views and materialized views.
Read
- https://stackoverflow.com/questions/48407329/cant-able-to-create-views-in-mysql-using-sequelize-orm
- https://github.com/sequelize/sequelize/issues/7197
- https://github.com/sequelize/sequelize/issues/3078
Install
npm install --save sequelize-mv-supportHow to use
All the original Sequelize methods and options still work with this module, you can read about those in the sequelize api docs. New and updated methods are documented in the api docs section of this readme.
First, when creating the sequelize instance, you have to do it using this package and not the Sequelize's:
sequelize.js:
const Sequelize = require('sequelize-mv-support');
// or
const { Sequelize, DataTypes } = require('sequelize-mv-support');
// or
import Sequelize from 'sequelize-mv-support';
// or
import { Sequelize } from 'sequelize-mv-support';
const sequelize = new Sequelize(
// Use the same construction call you've been using so far
);Then, when creating your view models you have to set two more options (let's call this view Foo):
models/foo.js:
import Sequelize from 'sequelize-mv-support';
// create an instance of sequelize
const sequelize = new Sequelize(
// Use the same construction call you've been using so far
);
const Foo = sequelize.define('foo', {
field1: Sequelize.DATE,
field2: Sequelize.STRING,
// etc...
},
{
treatAsView: true,
viewDefinition: 'SELECT field1, field2 from items'
}
);
(async () = {
// sync your models
await sequelize.sync();
// query the model as usual
const fooItems = await Foo.findAll();
})();Then, when creating materialized view models you have to set two more options (let's call this materialized view Bar):
models/bar.js:
import Sequelize from 'sequelize-mv-support';
// create an instance of sequelize
const sequelize = new Sequelize(
// Use the same construction call you've been using so far
);
// define your materialized view model
const Bar = sequelize.define('bar', {
field1: Sequelize.DATE,
field2: Sequelize.STRING,
// etc...
},
{
treatAsMaterializedView: true,
materializedViewDefinition: 'SELECT field1, field2 from items'
}
);
(async () => {
// sync your models
await sequelize.sync();
// refresh your materialized views as needed
await Bar.refreshMaterializedView();
// query the model as usual
const barItems = await Bar.findAll();
})();That's it. Take into account that views will be created after syncing all your models. This is because your views may depend on models.
API
Table of Contents
ModelOptionsWithViews
Extends ModelOptions
Interface describing the options property on a model
Model
Extends ModelOrig
Model with view support added
options
Type: OptionsType
queryInterface
Type: QueryInterfaceWithViews
drop
Parameters
optionsDropOptionsType (optional, default{})
Returns any
sync
Parameters
optionsSyncOptions
Returns any
syncView
Executes the query to create a view
Returns Promise\[[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\<unknown, unknown]> Result of the create view request
syncMaterializedView
Executes the query to create a materialized view
Returns Promise\[[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\<unknown, unknown]> Result of the create materialized view request
getViewDefinition
Gets the sql definition for this view
Returns string SQL query string to create a view
getMaterializedViewDefinition
Gets the sql definition for this materialized view
Returns string SQL query string to create the materialized view
refreshMaterializedView
Refreshes the materialized view in the database
Returns Promise\[[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\<unknown, unknown]>
QueryInterfaceWithViews
src/SequelizeWithViews.ts:81-99
Extends SequelizeOrig.QueryInterface
Extended query interface including support for creating and dropping views
Sequelize
src/SequelizeWithViews.ts:107-386
Extends SequelizeOrig.Sequelize
Sequelize class with view support
getQueryInterface
src/SequelizeWithViews.ts:150-205
Returns QueryInterfaceWithViews
define
src/SequelizeWithViews.ts:292-308
Define a new model, representing a table in the database.
The table columns are defined by the object that is given as the second argument. Each key of the object represents a column
Parameters
modelNamestring The name of the model. The model will be stored insequelize.modelsunder this nameattributesObject An object, where each attribute is a column of the table. Each column can be either a DataType, a string or a type-description object, with the properties described below:attributes.column(string | DataTypes | Object) The description of a database columnattributes.column.type(string | DataTypes) A string or a data typeattributes.column.allowNullboolean If false, the column will have a NOT NULL constraint, and a not null validation will be run before an instance is saved. (optional, defaulttrue)attributes.column.defaultValueany A literal default value, a JavaScript function, or an SQL function (seesequelize.fn) (optional, defaultnull)attributes.column.unique(string | boolean) If true, the column will get a unique constraint. If a string is provided, the column will be part of a composite unique index. If multiple columns have the same string, they will be part of the same unique index (optional, defaultfalse)attributes.column.primaryKeyboolean If true, this attribute will be marked as primary key (optional, defaultfalse)attributes.column.fieldstring If set, sequelize will map the attribute name to a different name in the database (optional, defaultnull)attributes.column.autoIncrementboolean If true, this column will be set to auto increment (optional, defaultfalse)attributes.column.autoIncrementIdentityboolean If true, combined with autoIncrement=true, will use PostgresGENERATED BY DEFAULT AS IDENTITYinstead ofSERIAL. Postgres 10+ only. (optional, defaultfalse)attributes.column.commentstring Comment for this column (optional, defaultnull)attributes.column.references(string | Model) An object with reference configurations (optional, defaultnull)attributes.column.onUpdatestring? What should happen when the referenced key is updated. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTIONattributes.column.onDeletestring? What should happen when the referenced key is deleted. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTIONattributes.column.getFunction? Provide a custom getter for this column. Usethis.getDataValue(String)to manipulate the underlying values.attributes.column.setFunction? Provide a custom setter for this column. Usethis.setDataValue(String, Value)to manipulate the underlying values.attributes.column.validateObject? An object of validations to execute for this column every time the model is saved. Can be either the name of a validation provided by validator.js, a validation function provided by extending validator.js (see theDAOValidatorproperty for more details), or a custom validation function. Custom validation functions are called with the value of the field and the instance itself as thethisbinding, and can possibly take a second callback argument, to signal that they are asynchronous. If the validator is sync, it should throw in the case of a failed validation; if it is async, the callback should be called with the error text.
optionsObject These options are merged with the default define options provided to the Sequelize constructoroptions.sequelizeObject Define the sequelize instance to attach to the new Model. Throw error if none is provided.options.modelNamestring? Set name of the model. By default its same as Class name.options.defaultScopeObject Define the default search scope to use for this model. Scopes have the same form as the options passed to find / findAll (optional, default{})options.scopesObject? More scopes, defined in the same way as defaultScope above. SeeModel.scopefor more information about how scopes are defined, and what you can do with themoptions.omitNullboolean? Don't persist null values. This means that all columns with null values will not be savedoptions.timestampsboolean Adds createdAt and updatedAt timestamps to the model. (optional, defaulttrue)options.paranoidboolean Callingdestroywill not delete the model, but instead set adeletedAttimestamp if this is true. Needstimestamps=trueto work (optional, defaultfalse)options.underscoredboolean Add underscored field to all attributes, this covers user defined attributes, timestamps and foreign keys. Will not affect attributes with explicitly setfieldoption (optional, defaultfalse)options.freezeTableNameboolean If freezeTableName is true, sequelize will not try to alter the model name to get the table name. Otherwise, the model name will be pluralized (optional, defaultfalse)options.nameObject? An object with two attributes,singularandplural, which are used when this model is associated to others.options.indexesArray[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)? indexes definitionsoptions.createdAt(string | boolean)? Override the name of the createdAt attribute if a string is provided, or disable it if false. Timestamps must be true. Underscored field will be set with underscored setting.options.updatedAt(string | boolean)? Override the name of the updatedAt attribute if a string is provided, or disable it if false. Timestamps must be true. Underscored field will be set with underscored setting.options.deletedAt(string | boolean)? Override the name of the deletedAt attribute if a string is provided, or disable it if false. Timestamps must be true. Underscored field will be set with underscored setting.options.tableNamestring? Defaults to pluralized model name, unless freezeTableName is true, in which case it uses model name verbatimoptions.schemastring schema (optional, default'public')options.enginestring? Specify engine for model's tableoptions.charsetstring? Specify charset for model's tableoptions.commentstring? Specify comment for model's tableoptions.collatestring? Specify collation for model's tableoptions.initialAutoIncrementstring? Set the initial AUTO_INCREMENT value for the table in MySQL.options.hooksObject? An object of hook function that are called before and after certain lifecycle events. The possible hooks are: beforeValidate, afterValidate, validationFailed, beforeBulkCreate, beforeBulkDestroy, beforeBulkUpdate, beforeCreate, beforeDestroy, beforeUpdate, afterCreate, beforeSave, afterDestroy, afterUpdate, afterBulkCreate, afterSave, afterBulkDestroy and afterBulkUpdate. See Hooks for more information about hook functions and their signatures. Each property can either be a function, or an array of functions.options.validateObject? An object of model wide validations. Validations have access to all model values viathis. If the validator function takes an argument, it is assumed to be async, and is called with a callback that accepts an optional error.options.treatAsMaterializedViewboolean Whether to treat this model as a materialised view (optional, defaultfalse)options.treatAsViewboolean Whether to treat this model as a view (optional, defaultfalse)options.viewDefinitionstring? The query to be represented by a viewoptions.materializedViewDefinitionstring? The query to be represented by a materialized view
stringstring [].name] The name of the index. Defaults to model name + _ + fields concatenatedstringstring [].type] Index type. Only used by mysql. One ofUNIQUE,FULLTEXTandSPATIALstringstring [].using] The method to create the index by (USINGstatement in SQL). BTREE and HASH are supported by mysql and postgres, and postgres additionally supports GIST and GIN.stringstring [].operator] Specify index operator.booleanboolean [].unique=false] Should the index by unique? Can also be triggered by setting type toUNIQUEbooleanboolean [].concurrently=false] PostgresSQL will build the index without taking any write locks. Postgres only
Examples
sequelize.define(
viewName,
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
},
name: Sequelize.STRING,
},
{
freezeTableName: true,
treatAsView: true,
viewDefinition: 'SELECT id, name from items',
}
);
sequelize.models.modelName // The model will now be available in models under the name given to defineReturns Model Newly defined model
sync
src/SequelizeWithViews.ts:325-331
Sync all defined models to the DB.
Parameters
optionsObject sync options (optional, default{})options.forceboolean If force is true, each Model will runDROP TABLE IF EXISTS, before it tries to create its own table (optional, defaultfalse)options.matchRegExp? Match a regex against the database name before syncing, a safety check for cases where force: true is used in tests but not live codeoptions.logging(boolean | Function) A function that logs sql queries, or false for no logging (optional, defaultconsole.log)options.schemastring The schema that the tables should be created in. This can be overridden for each table in sequelize.define (optional, default'public')options.searchPathstring An optional parameter to specify the schema search_path (Postgres only) (optional, defaultDEFAULT)options.hooksboolean If hooks is true then beforeSync, afterSync, beforeBulkSync, afterBulkSync hooks will be called (optional, defaulttrue)options.alter(boolean | Object) Alters tables to fit models. Provide an object for additional configuration. Not recommended for production use. If not further configured deletes data in columns that were removed or had their type changed in the model. (optional, defaultfalse)options.alter.dropboolean Prevents any drop statements while altering a table when set tofalse(optional, defaulttrue)
Returns Promise
syncViews
src/SequelizeWithViews.ts:339-343
Executes the create view query for each of the view definitions
Returns Promise[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\<any> The results of the create view queries
getViews
src/SequelizeWithViews.ts:351-357
Gets all the defined models which represent views
Returns Array\
syncMaterializedViews
src/SequelizeWithViews.ts:365-371
Executes the create materialized view query for each of the definitions
Returns Promise[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)\<any> The results of the create view queries
getMaterializedViews
src/SequelizeWithViews.ts:379-385
Gets all the defined models which represent materialized views
Returns Array\