@@ -197,7 +197,7 @@ CREATE TABLE IF NOT EXISTS "versions" (
Sometimes you may want to reference another table, without adding any constraints, or associations. In that case you can manually add the reference attributes to your schema definition, and mark the relations between them.
```js
```js
classTrainerextendsModel{}
Trainer.init({
firstName:Sequelize.STRING,
...
...
@@ -243,6 +243,7 @@ Trainer.hasMany(Series);
```
## One-To-One associations
One-To-One associations are associations between exactly two models connected by a single foreign key.
### BelongsTo
...
...
@@ -334,7 +335,7 @@ class User extends Model {}
User.init({/* ... */},{sequelize})
classProjectextendsModel{}
Project.init({/* ... */},{sequelize})
// One-way associations
Project.hasOne(User)
...
...
@@ -349,32 +350,32 @@ Project.hasOne(User)
You can also define the foreign key, e.g. if you already have an existing
database and want to work on it:
*/
Project.hasOne(User,{foreignKey:'initiator_id'})
/*
Because Sequelize will use the model's name (first parameter of define) for
the accessor methods, it is also possible to pass a special option to hasOne:
*/
Project.hasOne(User,{as:'Initiator'})
// Now you will get Project.getInitiator and Project.setInitiator
When we link two models in Sequelize we can refer them as pairs of **source** and **target** models. Like this
Having **Player** as the **source** and **Team** as the **target**
```js
Player.belongsTo(Team);
//Or
...
...
@@ -422,6 +424,7 @@ Player.hasOne(Team);
```
Having **Team** as the **source** and **Player** as the **target**
```js
Team.belongsTo(Player);
//Or
...
...
@@ -458,12 +461,13 @@ Coach.hasOne(Team) // `coachId` will be added on Team / Target model
## One-To-Many associations (hasMany)
One-To-Many associations are connecting one source with multiple targets. The targets however are again connected to exactly one specific source.
```js
classUserextendsModel{}
User.init({/* ... */},{sequelize})
classProjectextendsModel{}
Project.init({/* ... */},{sequelize})
// OK. Now things get more complicated (not really visible to the user :)).
// First let's define a hasMany association
Project.hasMany(User,{as:'Workers'})
...
...
@@ -502,6 +506,7 @@ Defining `through` is **required**. Sequelize would previously attempt to autoge
This will add methods `getUsers`, `setUsers`, `addUser`,`addUsers` to `Project`, and `getProjects`, `setProjects`, `addProject`, and `addProjects` to `User`.
Sometimes you may want to rename your models when using them in associations. Let's define users as workers and projects as tasks by using the alias (`as`) option. We will also manually define the foreign keys to use:
// This will create the table PersonChildren which stores the ids of the objects.
```
If you want additional attributes in your join table, you can define a model for the join table in sequelize, before you define the association, and then tell sequelize that it should use that model for joining, instead of creating a new one:
```js
...
...
@@ -532,7 +538,7 @@ class UserProjects extends Model {}
With Belongs-To-Many you can query based on **through** relation and select specific attributes. For example using `findAll` with **through**
```js
...
...
@@ -569,6 +576,7 @@ User.findAll({
}]
});
```
Belongs-To-Many creates a unique key when primary key is not present on through model. This unique key name can be overridden using **uniqueKey** option.
By default sequelize will use the model name (the name passed to `sequelize.define`) to figure out the name of the model when used in associations. For example, a model named `user` will add the functions `get/set/add User` to instances of the associated model, and a property named `.user` in eager loading, while a model named `User` will add the same functions, but a property named `.User` (notice the upper case U) in eager loading.
As we've already seen, you can alias models in associations using `as`. In single associations (has one and belongs to), the alias should be singular, while for many associations (has many) it should be plural. Sequelize then uses the [inflection][0]library to convert the alias to its singular form. However, this might not always work for irregular or non-english words. In this case, you can provide both the plural and the singular form of the alias:
As we've already seen, you can alias models in associations using `as`. In single associations (has one and belongs to), the alias should be singular, while for many associations (has many) it should be plural. Sequelize then uses the [inflection][0]library to convert the alias to its singular form. However, this might not always work for irregular or non-english words. In this case, you can provide both the plural and the singular form of the alias:
This section concerns association scopes. For a definition of association scopes vs. scopes on associated models, see [Scopes](/manual/scopes.html).
Association scopes allow you to place a scope (a set of default attributes for `get` and `create`) on the association. Scopes can be placed both on the associated model (the target of the association), and on the through table for n:m relations.
#### 1:n
Assume we have models Comment, Post, and Image. A comment can be associated to either an image or a post via `commentableId` and `commentable` - we say that Post and Image are `Commentable`
```js
...
...
@@ -858,6 +870,7 @@ image.addComment(comment);
The `getItem` utility function on `Comment` completes the picture - it simply converts the `commentable` string into a call to either `getImage` or `getPost`, providing an abstraction over whether a comment belongs to a post or an image. You can pass a normal options object as a parameter to `getItem(options)` to specify any where conditions or includes.
#### n:m
Continuing with the idea of a polymorphic model, consider a tag table - an item can have multiple tags, and a tag can be related to several items.
For brevity, the example only shows a Post model, but in reality Tag would be related to several other models.
You will need to call reload after updating an instance with a range type or use `returning: true` option.
**Special Cases**
#### Special Cases
```js
// empty range:
...
...
@@ -296,7 +296,6 @@ After a new range type has been [defined in postgres](https://www.postgresql.org
In this example the name of the postgres range type is `newtype_range` and the name of the underlying postgres datatype is `pg_new_type`. The key of `subtypes` and `castTypes` is the key of the Sequelize datatype `DataTypes.NEWTYPE.key`, in lower case.
```js
// myproject/lib/sequelize-additions.js
...
...
@@ -328,4 +327,3 @@ modules.exports = function sequelizeAdditions(Sequelize) {
```
The new range can be used in model definitions as `Sequelize.RANGE(Sequelize.NEWTYPE)` or `DataTypes.RANGE(DataTypes.NEWTYPE)`.
@@ -6,7 +6,7 @@ For a full list of hooks, see [Hooks file](https://github.com/sequelize/sequeliz
## Order of Operations
```
```text
(1)
beforeBulkCreate(instances, options)
beforeBulkDestroy(options)
...
...
@@ -42,6 +42,7 @@ For a full list of hooks, see [Hooks file](https://github.com/sequelize/sequeliz
```
## Declaring Hooks
Arguments to hooks are passed by reference. This means, that you can change the values, and this will be reflected in the insert / update statement. A hook may contain async actions - in this case the hook function should return a promise.
There are currently three ways to programmatically add hooks:
You can have many hooks with same name. Calling `.removeHook()` will remove all of them.
## Global / universal hooks
Global hooks are hooks which are run for all models. They can define behaviours that you want for all your models, and are especially useful for plugins. They can be defined in two ways, which have slightly different semantics:
### Default Hooks (Sequelize.options.define)
```js
constsequelize=newSequelize(...,{
define:{
...
...
@@ -143,6 +146,7 @@ Project.create() // Runs its own hook (because the global hook is overwritten)
```
### Permanent Hooks (Sequelize.addHook)
```js
sequelize.addHook('beforeCreate',()=>{
// Do stuff
...
...
@@ -184,7 +188,7 @@ new Sequelize(..., {
Sequelize provides two hooks that are executed immediately before and after a database connection is obtained:
```
```text
beforeConnect(config)
afterConnect(connection, config)
```
...
...
@@ -208,7 +212,7 @@ These hooks may _only_ be declared as a permanent global hook, as the connection
The following hooks will emit whenever you're editing a single object
Sometimes you'll be editing more than one record at a time by utilizing the `bulkCreate, update, destroy` methods on the model. The following will emit whenever you're using one of those methods:
```
```text
beforeBulkCreate(instances, options)
beforeBulkUpdate(options)
beforeBulkDestroy(options)
...
...
@@ -353,7 +357,6 @@ If your association is of type `n:m`, you may be interested in firing hooks on t
This can be simply solved by passing `{individualHooks: true}` to the `remove` call, resulting on each hook to be called on each removed through instance object.
## A Note About Transactions
Note that many model operations in Sequelize allow you to specify a transaction in the options parameter of the method. If a transaction _is_ specified in the original call, it will be present in the options parameter passed to the hook function. For example, consider the following snippet:
While out of the box Sequelize will seem a bit opinionated it's easy to work legacy tables and forward proof your application by defining (otherwise generated) table and field names.
## Tables
```js
classUserextendsModel{}
User.init({
...
...
@@ -14,6 +15,7 @@ User.init({
```
## Fields
```js
classMyModelextendsModel{}
MyModel.init({
...
...
@@ -25,6 +27,7 @@ MyModel.init({
```
## Primary keys
Sequelize will assume your table has a `id` primary key property by default.
To define your own primary key:
...
...
@@ -51,6 +54,7 @@ Collection.init({
And if your model has no primary key at all you can use `Model.removeAttribute('id');`
To create an empty project you will need to execute `init` command
```bash
...
...
@@ -28,6 +30,7 @@ This will create following folders
-`seeders`, contains all seed files
#### Configuration
Before continuing further we will need to tell CLI how to connect to database. To do that let's open default config file `config/config.json`. It looks something like this
```json
...
...
@@ -61,6 +64,7 @@ Now edit this file and set correct database credentials and dialect.
**Note:** _If your database doesn't exists yet, you can just call `db:create` command. With proper access it will create that database for you._
### Creating first Model (and Migration)
Once you have properly configured CLI config file you are ready to create your first migration. It's as simple as executing a simple command.
We will use `model:generate` command. This command requires two options
...
...
@@ -82,6 +86,7 @@ This will do following
**Note:** _Sequelize will only use Model files, it's the table representation. On the other hand, the migration file is a change in that model or more specifically that table, used by CLI. Treat migrations like a commit or a log for some change in database._
### Running Migrations
Until this step, we haven't inserted anything into the database. We have just created required model and migration files for our first model `User`. Now to actually create that table in database you need to run `db:migrate` command.
```bash
...
...
@@ -95,6 +100,7 @@ This command will execute these steps:
- Creates a table called `Users` with all columns as specified in its migration file.
### Undoing Migrations
Now our table has been created and saved in database. With migration you can revert to old state by just running a command.
You can use `db:migrate:undo`, this command will revert most recent migration.
Suppose we want to insert some data into a few tables by default. If we follow up on previous example we can consider creating a demo user for `User` table.
To manage all data migrations you can use seeders. Seed files are some change in data that can be used to populate database table with sample data or test data.
...
...
@@ -144,6 +151,7 @@ module.exports = {
```
### Running Seeds
In last step you have create a seed file. It's still not committed to database. To do that we need to run a simple command.
```bash
...
...
@@ -155,6 +163,7 @@ This will execute that seed file and you will have a demo user inserted into `Us
**Note:** _Seeders execution is not stored anywhere unlike migrations, which use the `SequelizeMeta` table. If you wish to override this please read `Storage` section_
### Undoing Seeds
Seeders can be undone if they are using any storage. There are two commands available for that:
The following skeleton shows a typical migration file.
```js
...
...
@@ -213,6 +223,7 @@ module.exports = {
```
The following is an example of a migration that performs two changes in the database, using a transaction to ensure that all instructions are successfully executed or rolled back in case of failure:
```js
module.exports={
up:(queryInterface,Sequelize)=>{
...
...
@@ -240,6 +251,7 @@ module.exports = {
```
### The `.sequelizerc` File
This is a special configuration file. It lets you specify various options that you would usually pass as arguments to CLI. Some scenarios where you can use it.
- You want to override default path to `migrations`, `models`, `seeders` or `config` folder.
...
...
@@ -274,6 +286,7 @@ With this config you are telling CLI to
- Use `db/migrations` as migrations folder
### Dynamic Configuration
Configuration file is by default a JSON file called `config.json`. But sometimes you want to execute some code or access environment variables which is not possible in JSON files.
Sequelize CLI can read from both `JSON` and `JS` files. This can be setup with `.sequelizerc` file. Let see how
...
...
@@ -325,8 +338,8 @@ module.exports = {
};
```
### Using Babel
Now you know how to use `.sequelizerc` file. Now let's see how to use this file to use babel with `sequelize-cli` setup. This will allow you to write migrations and seeders with ES6/ES7 syntax.
First install `babel-register`
...
...
@@ -334,6 +347,7 @@ First install `babel-register`
```bash
$ npm i --save-dev babel-register
```
Now let's create `.sequelizerc` file, it can include any configuration you may want to change for `sequelize-cli` but in addition to that we want it to register babel for our codebase. Something like this
```bash
...
...
@@ -357,8 +371,8 @@ module.exports = {
Now CLI will be able to run ES6/ES7 code from migrations/seeders etc. Please keep in mind this depends upon your configuration of `.babelrc`. Please read more about that at [babeljs.io](https://babeljs.io).
### Using Environment Variables
With CLI you can directly access the environment variables inside the `config/config.js`. You can use `.sequelizerc` to tell CLI to use `config/config.js` for configuration. This is explained in last section.
Then you can just expose file with proper environment variables.
...
...
@@ -390,6 +404,7 @@ module.exports = {
```
### Specifying Dialect Options
Sometime you want to specify a dialectOption, if it's a general config you can just add it in `config/config.json`. Sometime you want to execute some code to get dialectOptions, you should use dynamic config file for those cases.
```json
...
...
@@ -404,6 +419,7 @@ Sometime you want to specify a dialectOption, if it's a general config you can j
```
### Production Usages
Some tips around using CLI and migration setup in production environment.
1) Use environment variables for config settings. This is better achieved with dynamic configuration. A sample production safe configuration may look like.
...
...
@@ -444,14 +460,15 @@ module.exports = {
Our goal is to use environment variables for various database secrets and not accidentally check them in to source control.
### Storage
There are three types of storage that you can use: `sequelize`, `json`, and `none`.
-`sequelize` : stores migrations and seeds in a table on the sequelize database
-`json` : stores migrations and seeds on a json file
-`none` : does not store any migration/seed
#### Migration Storage
By default the CLI will create a table in your database called `SequelizeMeta` containing an entry
for each executed migration. To change this behavior, there are three options you can add to the
configuration file. Using `migrationStorage`, you can choose the type of storage to be used for
...
...
@@ -489,6 +506,7 @@ providing the `migrationStorageTableSchema` property.
aware of the implications of having no record of what migrations did or didn't run._
#### Seed Storage
By default the CLI will not save any seed that is executed. If you choose to change this behavior (!),
you can use `seederStorage` in the configuration file to change the storage type. If you choose `json`,
you can specify the path of the file using `seederStoragePath` or the CLI will write to the file
...
...
@@ -514,6 +532,7 @@ specify the table name using `seederStorageTableName`, or it will default to `Se
```
### Configuration Connection String
As an alternative to the `--config` option with configuration files defining your database, you can
use the `--url` option to pass in a connection string. For example:
Sequelize has a [sister library][1] for programmatically handling execution and logging of migration tasks.
## Query Interface
Using `queryInterface` object described before you can change database schema. To see full list of public methods it supports check [QueryInterface API][2]
If you do not want timestamps on your models, only want some timestamps, or you are working with an existing database where the columns are named something else, jump straight on to [configuration ][0]to see how to do that.
If you do not want timestamps on your models, only want some timestamps, or you are working with an existing database where the columns are named something else, jump straight on to [configuration][0] to see how to do that.
## Deferrable
...
...
@@ -223,7 +222,6 @@ sequelize.define('Foo', {
});
```
### Helper functions for use inside getter and setter definitions
* retrieving an underlying property value - always use `this.getDataValue()`
This extra capability is useful when, for example, `Error: Cannot find module` is thrown even though `/path/to/models/project` seems to be correct. Some frameworks, such as Meteor, overload `require`, and spit out "surprise" results like :
It support includes. Only the includes that are marked as `required` will be added to the count part:
Suppose you want to find all users who have a profile attached:
```js
User.findAndCountAll({
include:[
...
...
@@ -147,10 +150,10 @@ User.findAndCountAll({
The query above will only count users who have an active profile, because `required` is implicitly set to true when you add a where clause to the include.
The options object that you pass to `findAndCountAll` is the same as for `findAll` (described below).
### `findAll` - Search for multiple elements in the database
Notice that the accessor (the `Tasks` property in the resulting instance) is plural because the association is many-to-something.
If an association is aliased (using the `as` option), you must specify this alias when including the model. Notice how the user's `Tool`s are aliased as `Instruments` above. In order to get that right you have to specify the model you want to load, as well as the alias:
```js
...
...
@@ -694,6 +696,7 @@ Company.findAll({
```
### Nested eager loading
You can use nested eager loading to load all related models of a related model:
Replacements in a query can be done in two different ways, either using named parameters (starting with `:`), or unnamed, represented by a `?`. Replacements are passed in the options object.
* If an array is passed, `?` will be replaced in the order that they appear in the array
...
...
@@ -76,6 +77,7 @@ sequelize.query('SELECT * FROM users WHERE name LIKE :search_name ',
```
## Bind Parameter
Bind parameters are like replacements. Except replacements are escaped and inserted into the query by sequelize before the query is sent to the database, while bind parameters are sent to the database outside the SQL query text. A query can have either bind parameters or replacements. Bind parameters are referred to by either $1, $2, ... (numeric) or $key (alpha-numeric). This is independent of the dialect.
* If an array is passed, `$1` is bound to the 1st element in the array (`bind[0]`)
...
...
@@ -99,4 +101,3 @@ sequelize.query('SELECT *, "text with literal $$1 and literal $$status" as t FRO
*[meteor modeler](https://www.datensen.com/) - Desktop tool for visual definition of Sequelize models and asssociations.
*[sequelize-ui](https://github.com/tomjschuster/sequelize-ui) - Online tool for building models, relations and more.
*[sequelizer](https://github.com/andyforever/sequelizer) - A GUI Desktop App for generating Sequelize models. Support for Mysql, Mariadb, Postgres, Sqlite, Mssql.
...
...
@@ -15,35 +17,45 @@
*[sequelizejs-decorators](https://www.npmjs.com/package/sequelizejs-decorators) decorators for composing sequelize models
### Autoloader
*[sequelize-autoload](https://github.com/boxsnake-nodejs/sequelize-autoload) - An autoloader for Sequelize, inspired by [PSR-0](https://www.php-fig.org/psr/psr-0/) and [PSR-4](https://www.php-fig.org/psr/psr-4/).
*[sequelize-slugify](https://www.npmjs.com/package/sequelize-slugify) - Add slugs to sequelize models
### Tokens
*[sequelize-tokenify](https://github.com/pipll/sequelize-tokenify) - Add unique tokens to sequelize models
### Miscellaneous
*[sequelize-deep-update](https://www.npmjs.com/package/sequelize-deep-update) - Update a sequelize instance and its included associated instances with new properties.
*[sequelize-noupdate-attributes](https://www.npmjs.com/package/sequelize-noupdate-attributes) - Adds no update/readonly attributes support to models.
*[sequelize-joi](https://www.npmjs.com/package/sequelize-joi) - Allows specifying [Joi](https://github.com/hapijs/joi) validation schema for JSONB model attributes in Sequelize.
@@ -61,6 +61,7 @@ The default scope can be removed by calling `.unscoped()`, `.scope(null)`, or by
```js
Project.scope('deleted').findAll();// Removes the default scope
```
```sql
SELECT*FROMprojectsWHEREdeleted=true
```
...
...
@@ -77,6 +78,7 @@ activeUsers: {
```
## Usage
Scopes are applied by calling `.scope` on the model definition, passing the name of one or more scopes. `.scope` returns a fully functional model instance with all the regular methods: `.findAll`, `.update`, `.count`, `.destroy` etc. You can save this model instance and reuse it later:
```js
...
...
@@ -96,11 +98,13 @@ Scopes which are functions can be invoked in two ways. If the scope does not tak
@@ -258,6 +265,7 @@ The merge illustrated above works in the exact same way regardless of the order
This merge strategy also works in the exact same way with options passed to `.findAll`, `.findOne` and the like.
## Associations
Sequelize has two different but related scope concepts in relation to associations. The difference is subtle but important:
***Association scopes** Allow you to specify default attributes when getting and setting associations - useful when implementing polymorphic associations. This scope is only invoked on the association between the two models, when using the `get`, `set`, `add` and `create` associated model functions
...
...
@@ -281,6 +289,7 @@ When calling `post.getComments()`, this will automatically add `WHERE commentabl
Consider then, that Post has a default scope which only shows active posts: `where: { active: true }`. This scope lives on the associated model (Post), and not on the association like the `commentable` scope did. Just like the default scope is applied when calling `Post.findAll()`, it is also applied when calling `User.getPosts()` - this will only return the active posts for that user.
To disable the default scope, pass `scope: null` to the getter: `User.getPosts({ scope: null })`. Similarly, if you want to apply other scopes, pass an array like you would to `.scope`:
@@ -97,7 +97,6 @@ After you've used `Sequelize.useCLS()` all promises returned from sequelize will
**Note:** _[CLS only supports async/await, at the moment, when using cls-hooked package](https://github.com/othiym23/node-continuation-local-storage/issues/98#issuecomment-323503807). Although, [cls-hooked](https://github.com/Jeff-Lewis/cls-hooked/blob/master/README.md) relies on *experimental API*[async_hooks](https://github.com/nodejs/node/blob/master/doc/api/async_hooks.md)_
## Concurrent/Partial transactions
You can have concurrent transactions within a sequence of queries or have some of them excluded from any transactions. Use the `{transaction: }` option to control which transaction a query belong to:
...
...
@@ -105,6 +104,7 @@ You can have concurrent transactions within a sequence of queries or have some o
**Warning:** _SQLite does not support more than one transaction at the same time._
**Note:** _The SET ISOLATION LEVEL queries are not logged in case of MSSQL as the specified isolationLevel is passed directly to tedious_
## Unmanaged transaction (then-callback)
Unmanaged transactions force you to manually rollback or commit the transaction. If you don't do that, the transaction will hang until it times out. To start an unmanaged transaction, call `sequelize.transaction()` without a callback (you can still pass an options object) and call `then` on the returned promise. Notice that `commit()` and `rollback()` returns a promise.
@@ -12,7 +12,7 @@ Sequelize v5 will only support Node 6 and up [#9015](https://github.com/sequeliz
With v4 you started to get a deprecation warning `String based operators are now deprecated`. Also concept of operators was introduced. These operators are Symbols which prevent hash injection attacks.
@@ -48,7 +48,6 @@ With v5 if `deletedAt` is set, record will be considered as deleted. `paranoid`
`updateOnDuplicate` option which used to accept boolean and array, now only accepts non-empty array of attributes. [#9288](https://github.com/sequelize/sequelize/issues/9288)
**Underscored Mode**
Implementation of `Model.options.underscored` is changed. You can find full specifications [here](https://github.com/sequelize/sequelize/issues/6423#issuecomment-379472035).
...
...
@@ -72,7 +71,7 @@ Many model based aliases has been removed [#9372](https://github.com/sequelize/s
| findAndCount | findAndCountAll |
| findOrInitialize | findOrBuild |
| updateAttributes | update |
| findById, findByPrimary| findByPk |
| findById, findByPrimary| findByPk |
| all | findAll |
| hook | addHook |
...
...
@@ -110,14 +109,14 @@ Prototype references for many constants, objects and classes has been removed [#