sequelize-mv-support
v4.1.2
Published
Adds materialized views support to Sequelize.
Downloads
1,783
Maintainers
Readme
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-support
How 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
options
DropOptionsType (optional, default{}
)
Returns any
sync
Parameters
options
SyncOptions
Returns any
syncView
Executes the query to create a view
Returns Promise<[Array<unknown>, unknown]> Result of the create view request
syncMaterializedView
Executes the query to create a materialized view
Returns Promise<[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<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
modelName
string The name of the model. The model will be stored insequelize.models
under this nameattributes
Object 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.allowNull
boolean 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.defaultValue
any 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.primaryKey
boolean If true, this attribute will be marked as primary key (optional, defaultfalse
)attributes.column.field
string If set, sequelize will map the attribute name to a different name in the database (optional, defaultnull
)attributes.column.autoIncrement
boolean If true, this column will be set to auto increment (optional, defaultfalse
)attributes.column.autoIncrementIdentity
boolean If true, combined with autoIncrement=true, will use PostgresGENERATED BY DEFAULT AS IDENTITY
instead ofSERIAL
. Postgres 10+ only. (optional, defaultfalse
)attributes.column.comment
string Comment for this column (optional, defaultnull
)attributes.column.references
(string | Model) An object with reference configurations (optional, defaultnull
)attributes.column.onUpdate
string? What should happen when the referenced key is updated. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTIONattributes.column.onDelete
string? What should happen when the referenced key is deleted. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTIONattributes.column.get
Function? Provide a custom getter for this column. Usethis.getDataValue(String)
to manipulate the underlying values.attributes.column.set
Function? Provide a custom setter for this column. Usethis.setDataValue(String, Value)
to manipulate the underlying values.attributes.column.validate
Object? 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 theDAOValidator
property for more details), or a custom validation function. Custom validation functions are called with the value of the field and the instance itself as thethis
binding, 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.
options
Object These options are merged with the default define options provided to the Sequelize constructoroptions.sequelize
Object Define the sequelize instance to attach to the new Model. Throw error if none is provided.options.modelName
string? Set name of the model. By default its same as Class name.options.defaultScope
Object 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.scopes
Object? More scopes, defined in the same way as defaultScope above. SeeModel.scope
for more information about how scopes are defined, and what you can do with themoptions.omitNull
boolean? Don't persist null values. This means that all columns with null values will not be savedoptions.timestamps
boolean Adds createdAt and updatedAt timestamps to the model. (optional, defaulttrue
)options.paranoid
boolean Callingdestroy
will not delete the model, but instead set adeletedAt
timestamp if this is true. Needstimestamps=true
to work (optional, defaultfalse
)options.underscored
boolean Add underscored field to all attributes, this covers user defined attributes, timestamps and foreign keys. Will not affect attributes with explicitly setfield
option (optional, defaultfalse
)options.freezeTableName
boolean 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.name
Object? An object with two attributes,singular
andplural
, which are used when this model is associated to others.options.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.tableName
string? Defaults to pluralized model name, unless freezeTableName is true, in which case it uses model name verbatimoptions.schema
string schema (optional, default'public'
)options.engine
string? Specify engine for model's tableoptions.charset
string? Specify charset for model's tableoptions.comment
string? Specify comment for model's tableoptions.collate
string? Specify collation for model's tableoptions.initialAutoIncrement
string? Set the initial AUTO_INCREMENT value for the table in MySQL.options.hooks
Object? 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.validate
Object? 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.treatAsMaterializedView
boolean Whether to treat this model as a materialised view (optional, defaultfalse
)options.treatAsView
boolean Whether to treat this model as a view (optional, defaultfalse
)options.viewDefinition
string? The query to be represented by a viewoptions.materializedViewDefinition
string? The query to be represented by a materialized view
string
string [].name] The name of the index. Defaults to model name + _ + fields concatenatedstring
string [].type] Index type. Only used by mysql. One ofUNIQUE
,FULLTEXT
andSPATIAL
string
string [].using] The method to create the index by (USING
statement in SQL). BTREE and HASH are supported by mysql and postgres, and postgres additionally supports GIST and GIN.string
string [].operator] Specify index operator.boolean
boolean [].unique=false] Should the index by unique? Can also be triggered by setting type toUNIQUE
boolean
boolean [].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 define
Returns Model Newly defined model
sync
src/SequelizeWithViews.ts:325-331
Sync all defined models to the DB.
Parameters
options
Object sync options (optional, default{}
)options.force
boolean If force is true, each Model will runDROP TABLE IF EXISTS
, before it tries to create its own table (optional, defaultfalse
)options.match
RegExp? 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.schema
string The schema that the tables should be created in. This can be overridden for each table in sequelize.define (optional, default'public'
)options.searchPath
string An optional parameter to specify the schema search_path (Postgres only) (optional, defaultDEFAULT
)options.hooks
boolean 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.drop
boolean 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<any>> The results of the create view queries
getViews
src/SequelizeWithViews.ts:351-357
Gets all the defined models which represent views
Returns Array<any>
syncMaterializedViews
src/SequelizeWithViews.ts:365-371
Executes the create materialized view query for each of the definitions
Returns Promise<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<any>