不要怂,就是干,撸起袖子干!

Commit d136b216 by Wei-Liang Liou Committed by Sushant

docs: cleanup linting issues (#10685)

1 parent 061787f9
......@@ -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
class Trainer extends Model {}
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 })
class Project extends Model {}
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
 
// Or let's define some self references
class Person extends Model {}
Person.init({ /* ... */}, { sequelize })
 
Person.hasOne(Person, {as: 'Father'})
// this will add the attribute FatherId to Person
 
// also possible:
Person.hasOne(Person, {as: 'Father', foreignKey: 'DadId'})
// this will add the attribute DadId to Person
 
// In both cases you will be able to do:
Person.setFather
Person.getFather
 
// If you need to join a table twice you can double join the same table
Team.hasOne(Game, {as: 'HomeTeam', foreignKey : 'homeTeamId'});
Team.hasOne(Game, {as: 'AwayTeam', foreignKey : 'awayTeamId'});
......@@ -415,6 +416,7 @@ Team.init({/* attributes */}, { sequelize });
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
class User extends Model {}
User.init({/* ... */}, { sequelize })
class Project extends Model {}
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:
```js
User.belongsToMany(Project, { as: 'Tasks', through: 'worker_tasks', foreignKey: 'userId' })
Project.belongsToMany(User, { as: 'Workers', through: 'worker_tasks', foreignKey: 'projectId' })
......@@ -521,6 +526,7 @@ Person.belongsToMany(Person, { as: 'Children', through: 'PersonChildren' })
// 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 {}
UserProjects.init({
status: DataTypes.STRING
}, { sequelize })
 
User.belongsToMany(Project, { through: UserProjects })
Project.belongsToMany(User, { through: UserProjects })
```
......@@ -556,6 +562,7 @@ UserProjects.init({
status: DataTypes.STRING
}, { sequelize })
```
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.
```js
......@@ -579,7 +587,7 @@ Project.belongsToMany(User, { through: UserProjects, uniqueKey: 'my_custom_uniqu
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:
```js
User.belongsToMany(Project, { as: { singular: 'task', plural: 'tasks' }})
......@@ -597,7 +605,7 @@ Project.init(attributes, {
},
sequelize,
})
 
User.belongsToMany(Project);
```
......@@ -624,27 +632,27 @@ Because Sequelize is doing a lot of magic, you have to call `Sequelize.sync` aft
```js
Project.hasMany(Task)
Task.belongsTo(Project)
 
Project.create()...
Task.create()...
Task.create()...
 
// save them... and then:
project.setTasks([task1, task2]).then(() => {
// saved!
})
 
// ok, now they are saved... how do I get them later on?
project.getTasks().then(associatedTasks => {
// associatedTasks is an array of tasks
})
 
// You can also pass filters to the getter method.
// They are equal to the options you can pass to a usual finder method.
project.getTasks({ where: 'id > 10' }).then(tasks => {
// tasks with an id greater than 10 :)
})
 
// You can also only retrieve certain fields of a associated object.
project.getTasks({attributes: ['title']}).then(tasks => {
// retrieve tasks with the attributes "title" and "id"
......@@ -658,17 +666,17 @@ To remove created associations you can just call the set method without a specif
project.setTasks([task2]).then(associatedTasks => {
// you will get task2 only
})
 
// remove 'em all
project.setTasks([]).then(associatedTasks => {
// you will get an empty array
})
 
// or remove 'em more directly
project.removeTask(task1).then(() => {
// it's gone
})
 
// and add 'em again
project.addTask(task1).then(() => {
// it's back again
......@@ -699,17 +707,17 @@ project.UserProjects = {
status: 'active'
}
u.addProject(project)
 
// Or by providing a second options.through argument when adding the association, containing the data that should go in the join table
u.addProject(project, { through: { status: 'active' }})
 
 
// When associating multiple objects, you can combine the two options above. In this case the second argument
// will be treated as a defaults object, that will be used if no data is provided
project1.UserProjects = {
status: 'inactive'
}
 
u.setProjects([project1, project2], { through: { status: 'active' }})
// The code above will record inactive for project one, and active for project two in the join table
```
......@@ -719,10 +727,10 @@ When getting data on an association that has a custom join table, the data from
```js
u.getProjects().then(projects => {
const project = projects[0]
 
if (project.UserProjects.status === 'active') {
// .. do magic
 
// since this is a real DAO instance, you can save it directly after you are done doing magic
return project.UserProjects.save()
}
......@@ -737,6 +745,7 @@ user.getProjects({ attributes: ['name'], joinTableAttributes: ['status']})
```
## Check associations
You can also check if an object is already associated with another one (N:M only). Here is how you'd do it:
```js
......@@ -753,7 +762,7 @@ Project.create({ /* */ }).then(project => {
})
})
})
 
// check if all associated objects are as expected:
// let's assume we have already a project and two users
project.setUsers([user1, user2]).then(() => {
......@@ -765,14 +774,17 @@ project.setUsers([user1, user2]).then(() => {
// result would be true
})
```
## Advance Concepts
### Scopes
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.
......@@ -936,6 +949,7 @@ Post.belongsToMany(Tag, {
post.getPendingTags();
```
```sql
SELECT
"tag"."id",
......
......@@ -147,7 +147,7 @@ range // [{ value: Date, inclusive: false }, { value: Date, inclusive: true }]
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)`.
......@@ -90,8 +90,6 @@ Sequelize will keep the connection open by default, and use the same connection
## Modeling a table
Models are defined with `Sequelize.Model.init(attributes, options)`:
```js
......@@ -142,7 +140,7 @@ The Sequelize constructor takes a `define` option which will change the default
```js
const sequelize = new Sequelize(connectionURI, {
define: {
// The `timestamps` field specify whether or not the `createdAt` and `updatedAt` fields will be created.
// The `timestamps` field specify whether or not the `createdAt` and `updatedAt` fields will be created.
// This was true by default, but now is false by default
timestamps: false
}
......
......@@ -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:
......@@ -108,9 +109,11 @@ Book.removeHook('afterCreate', 'notifyUsers');
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
const sequelize = new Sequelize(..., {
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
```
```text
beforeValidate
afterValidate or validationFailed
beforeCreate / beforeUpdate / beforeDestroy
......@@ -244,7 +248,7 @@ User.create({username: 'Boss', accessLevel: 20}).then(user => {
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:
......
......@@ -9,7 +9,7 @@ const project = Project.build({
title: 'my awesome project',
description: 'woot woot. this will make me a rich man'
})
 
const task = Task.build({
title: 'specify the project idea',
description: 'bla',
......@@ -26,10 +26,10 @@ Task.init({
title: Sequelize.STRING,
rating: { type: Sequelize.TINYINT, defaultValue: 3 }
}, { sequelize });
 
// now instantiate an object
const task = Task.build({title: 'very important task'})
 
task.title // ==> 'very important task'
task.rating // ==> 3
```
......@@ -40,11 +40,11 @@ To get it stored in the database, use the `save`-method and catch the even
project.save().then(() => {
// my nice callback stuff
})
 
task.save().catch(error => {
// mhhh, wth!
})
 
// you can also build, save and access the object with chaining:
Task
.build({ title: 'foo', description: 'bar', deadline: new Date() })
......@@ -86,7 +86,7 @@ Now lets change some values and save changes to the database..&per
// way 1
task.title = 'a very different title now'
task.save().then(() => {})
 
// way 2
task.update({
title: 'a very different title now'
......@@ -101,7 +101,7 @@ task.description = 'baaaaaar'
task.save({fields: ['title']}).then(() => {
// title will now be 'foooo' but description is the very same as before
})
 
// The equivalent call using update looks like this:
task.update({ title: 'foooo', description: 'baaaaaar'}, {fields: ['title']}).then(() => {
// title will now be 'foooo' but description is the very same as before
......@@ -243,7 +243,7 @@ Tasks.init({
}
}
}, { sequelize })
 
Tasks.bulkCreate([
{name: 'foo', code: '123'},
{code: '1234'},
......@@ -285,9 +285,9 @@ Person.create({
plain: true
}))
})
 
// result:
 
// { name: 'Rambow',
// firstname: 'John',
// id: 1,
......@@ -306,7 +306,7 @@ If you need to get your instance in sync, you can use the method`reload`&p
Person.findOne({ where: { name: 'john' } }).then(person => {
person.name = 'jane'
console.log(person.name) // 'jane'
 
person.reload().then(() => {
console.log(person.name) // 'john'
})
......
......@@ -3,6 +3,7 @@
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
class User extends Model {}
User.init({
......@@ -14,6 +15,7 @@ User.init({
```
## Fields
```js
class MyModel extends Model {}
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');`
## Foreign keys
```js
// 1:1
Organization.belongsTo(User, { foreignKey: 'owner_id' });
......
......@@ -4,7 +4,7 @@
Sequelize library is distributed with MIT license. You can find original license [here.](https://github.com/sequelize/sequelize/blob/master/LICENSE)
```
```text
MIT License
Copyright (c) 2014-present Sequelize contributors
......@@ -30,7 +30,7 @@ SOFTWARE.
## AUTHOR(S)
```
```text
Main author:
Sascha Depold
......@@ -43,7 +43,7 @@ sascha [at] depold [dot] com
## INHALTLICHE VERANTWORTUNG
```
```text
Ich übernehme keine Haftung für ausgehende Links.
Daher musst du dich bei Problemen an deren Betreiber wenden!
```
......@@ -7,6 +7,7 @@ You will need [Sequelize CLI][0]. The CLI ships support for migrations and proje
## The CLI
### Installing CLI
Let's start with installing CLI, you can find instructions [here][0]. Most preferred way is installing locally like this
```bash
......@@ -14,6 +15,7 @@ $ npm install --save sequelize-cli
```
### Bootstrapping
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.
......@@ -110,6 +116,7 @@ $ npx sequelize db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js
```
### Creating First Seed
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:
If you wish to undo most recent seed
......@@ -178,6 +187,7 @@ $ npx sequelize db:seed:undo:all
## Advance Topics
### Migration Skeleton
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:
......@@ -535,13 +554,13 @@ $ npx sequelize db:migrate --url 'mysql://root:password@mysql_host.com/database_
```
### Programmatic use
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]
[0]: https://github.com/sequelize/cli
[1]: https://github.com/sequelize/umzug
[2]: /class/lib/query-interface.js~QueryInterface.html
......@@ -110,8 +110,7 @@ module.exports = {
```
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()`
......@@ -563,7 +561,7 @@ sequelize.import('project', (sequelize, DataTypes) => {
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 :
```
```text
Error: Cannot find module '/home/you/meteorApp/.meteor/local/build/programs/server/app/path/to/models/project.js'
```
......@@ -572,14 +570,13 @@ This is solved by passing in Meteor's version of `require`. So, while this proba
```js
const AuthorModel = db.import('./path/to/models/project');
```
... this should succeed ...
```js
const AuthorModel = db.import('project', require('./path/to/models/project'));
```
## Optimistic Locking
Sequelize has built-in support for optimistic locking through a model instance version count.
......@@ -674,6 +671,7 @@ User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
```
### Indexes
Sequelize supports adding indexes to the model definition which will be created during `Model.sync()` or `sequelize.sync`.
```js
......@@ -714,7 +712,6 @@ User.init({}, {
});
```
[0]: /manual/models-definition.html#configuration
[1]: /manual/data-types.html
[3]: https://github.com/chriso/validator.js
......
......@@ -7,6 +7,7 @@ Finder methods are intended to query data from the database. They do *not* retur
In this document we'll explore what finder methods can do:
### `find` - Search for one specific element in the database
```js
// search for known ids
Project.findByPk(123).then(project => {
......@@ -66,6 +67,7 @@ User
```
The code created a new instance. So when we already have an instance ...
```js
User.create({ username: 'fnord', job: 'omnomnom' })
.then(() => User.findOrCreate({where: {username: 'fnord'}, defaults: {job: 'something else'}}))
......@@ -125,6 +127,7 @@ Project
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
```js
// find multiple entries
Project.findAll().then(projects => {
......@@ -478,7 +481,6 @@ User.findAll({ include: [ Task ] }).then(users => {
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:
```js
......
......@@ -9,6 +9,7 @@ Model.findAll({
attributes: ['foo', 'bar']
});
```
```sql
SELECT foo, bar ...
```
......@@ -20,6 +21,7 @@ Model.findAll({
attributes: ['foo', ['bar', 'baz']]
});
```
```sql
SELECT foo, bar AS baz ...
```
......@@ -31,6 +33,7 @@ Model.findAll({
attributes: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
});
```
```sql
SELECT COUNT(hats) AS no_hats ...
```
......@@ -50,6 +53,7 @@ Model.findAll({
attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']] }
});
```
```sql
SELECT id, foo, bar, baz, quz, COUNT(hats) AS no_hats ...
```
......@@ -61,11 +65,11 @@ Model.findAll({
attributes: { exclude: ['baz'] }
});
```
```sql
SELECT id, foo, bar, quz ...
```
## Where
Whether you are querying with findAll/find or doing bulk updates/destroys you can pass a `where` object to filter the query.
......@@ -75,6 +79,7 @@ Whether you are querying with findAll/find or doing bulk updates/destroys you ca
It's also possible to generate complex AND/OR conditions by nesting sets of `or` and `and` `Operators`.
### Basics
```js
const Op = Sequelize.Op;
......@@ -136,6 +141,7 @@ Post.findAll({
### Operators
Sequelize exposes symbol operators that can be used for to create more complex comparisons -
```js
const Op = Sequelize.Op
......@@ -196,6 +202,7 @@ as well.
```
#### Combinations
```js
const Op = Sequelize.Op;
......@@ -351,6 +358,7 @@ User.findAll({
JSONB can be queried in three different ways.
#### Nested object
```js
{
meta: {
......@@ -364,6 +372,7 @@ JSONB can be queried in three different ways.
```
#### Nested key
```js
{
"meta.audio.length": {
......@@ -373,6 +382,7 @@ JSONB can be queried in three different ways.
```
#### Containment
```js
{
"meta": {
......@@ -386,6 +396,7 @@ JSONB can be queried in three different ways.
```
### Relations / Associations
```js
// Find all projects with a least one task where task.state === project.state
Project.findAll({
......
......@@ -36,6 +36,7 @@ sequelize
```
## Replacements
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
console.log(projects)
})
```
......@@ -3,10 +3,12 @@
## Addons & Plugins
### ACL
* [ssacl](https://github.com/pumpupapp/ssacl)
* [ssacl-attribute-roles](https://github.com/mickhansen/ssacl-attribute-roles)
### Auto Code Generation & Scaffolding
* [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/).
### Caching
* [sequelize-transparent-cache](https://github.com/DanielHreben/sequelize-transparent-cache)
### Filters
* [sequelize-transforms](https://www.npmjs.com/package/sequelize-transforms) - Add configurable attribute transforms.
### Fixtures / mock data
* [Fixer](https://github.com/olalonde/fixer)
* [Sequelize-fixtures](https://github.com/domasx2/sequelize-fixtures)
* [Sequelize-fixture](https://github.com/xudejian/sequelize-fixture)
### Hierarchies
* [sequelize-hierarchy](https://www.npmjs.com/package/sequelize-hierarchy) - Nested hierarchies for Sequelize.
### Historical records / Time travel
* [sequelize-temporal](https://github.com/bonaval/sequelize-temporal) - Temporal tables (aka historical records)
### Migrations
* [umzug](https://github.com/sequelize/umzug)
### Slugification
* [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 * FROM projects WHERE deleted = 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
```js
Project.scope('random', { method: ['accessLevel', 19]}).findAll();
```
```sql
SELECT * FROM projects WHERE someNumber = 42 AND accessLevel >= 19
```
## Merging
Several scopes can be applied simultaneously by passing an array of scopes to `.scope`, or by passing the scopes as consecutive arguments.
```js
......@@ -108,6 +112,7 @@ Several scopes can be applied simultaneously by passing an array of scopes to `.
Project.scope('deleted', 'activeUsers').findAll();
Project.scope(['deleted', 'activeUsers']).findAll();
```
```sql
SELECT * FROM projects
INNER JOIN users ON projects.userId = users.id
......@@ -119,6 +124,7 @@ If you want to apply another scope alongside the default scope, pass the key `de
```js
Project.scope('defaultScope', 'deleted').findAll();
```
```sql
SELECT * FROM projects WHERE active = true AND deleted = true
```
......@@ -164,6 +170,7 @@ Project.scope('deleted').findAll({
}
})
```
```sql
WHERE deleted = true AND firstName = 'john'
```
......@@ -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`:
```js
User.getPosts({ scope: ['scope1', 'scope2']});
```
......
......@@ -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._
### Without CLS enabled
```js
sequelize.transaction((t1) => {
return sequelize.transaction((t2) => {
......@@ -120,6 +120,7 @@ sequelize.transaction((t1) => {
```
## Isolation levels
The possible isolations levels to use when starting a transaction:
```js
......@@ -144,6 +145,7 @@ return sequelize.transaction({
**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.
```js
......@@ -165,6 +167,7 @@ return sequelize.transaction().then(t => {
```
## Options
The `transaction` method can be called with an options object as the first argument, that
allows the configuration of the transaction.
......@@ -224,6 +227,7 @@ If unsure, refer to the API documentation for the method you are using to be sur
A `transaction` object allows tracking if and when it is committed.
An `afterCommit` hook can be added to both managed and unmanaged transaction objects:
```js
sequelize.transaction(t => {
t.afterCommit((transaction) => {
......@@ -267,7 +271,7 @@ model.afterSave((instance, options) => {
Queries within a `transaction` can be performed with locks
```
```js
return User.findAll({
limit: 1,
lock: true,
......@@ -277,7 +281,7 @@ return User.findAll({
Queries within a transaction can skip locked rows
```
```js
return User.findAll({
limit: 1,
lock: true,
......
......@@ -3,14 +3,15 @@
Since v5 Sequelize provides it's own TypeScript definitions.
Please note that only TS >= 3.1 is supported.
## Installation:
## Installation
In order to avoid installation bloat for non TS users you must install the following packages manually:
- `@types/node` this is universally required
- `@types/validator`
- `@types/bluebird`
## Note
- `@types/node` this is universally required
- `@types/validator`
- `@types/bluebird`
## Note
As Sequelize heavily relies on runtime property assignments, TypeScript won't be very useful out of the box.
A decent amount of manual type declarations are needed to make models workable.
......@@ -131,7 +132,7 @@ async function stuff() {
## Legacy `.define` usage
TypeScript doesn't know how to generate a `class` definition when we use the legacy `.define`,
therefor we need to do some manual work and declare an interface and a type and eventually cast
therefor we need to do some manual work and declare an interface and a type and eventually cast
the result of `.define` to the _static_ type.
```ts
......
......@@ -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.
http://docs.sequelizejs.com/manual/querying.html#operators-security
[http://docs.sequelizejs.com/manual/querying.html#operators-security](http://docs.sequelizejs.com/manual/querying.html#operators-security)
**With v5**
......@@ -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 [#
| Removed in v5 | Official Alternative |
| :------ | :------ |
| Sequelize.prototype.Utils | Sequelize.Utils |
| Sequelize.prototype.Promise | Sequelize.Promise |
| Sequelize.prototype.TableHints | Sequelize.TableHints |
| Sequelize.prototype.Op | Sequelize.Op |
| Sequelize.prototype.Transaction | Sequelize.Transaction |
| Sequelize.prototype.Model | Sequelize.Model |
| Sequelize.prototype.Deferrable | Sequelize.Deferrable |
| Sequelize.prototype.Error | Sequelize.Error |
| Sequelize.prototype.Utils | Sequelize.Utils |
| Sequelize.prototype.Promise | Sequelize.Promise |
| Sequelize.prototype.TableHints | Sequelize.TableHints |
| Sequelize.prototype.Op | Sequelize.Op |
| Sequelize.prototype.Transaction | Sequelize.Transaction |
| Sequelize.prototype.Model | Sequelize.Model |
| Sequelize.prototype.Deferrable | Sequelize.Deferrable |
| Sequelize.prototype.Error | Sequelize.Error |
| Sequelize.prototype[error] | Sequelize[error] |
```js
......@@ -276,8 +275,6 @@ dialectOptions: {
- refactor: optimize memoize use, misc cases [#10122](https://github.com/sequelize/sequelize/pull/10122)
- chore(lint): enforce consistent spacing [#10193](https://github.com/sequelize/sequelize/pull/10193)
### 5.0.0-beta.14
- fix(query): correctly quote identifier for attributes (#9964) [#10118](https://github.com/sequelize/sequelize/pull/10118)
......@@ -303,7 +300,7 @@ dialectOptions: {
- fix: throw on undefined where parameters [#10048](https://github.com/sequelize/sequelize/pull/10048)
- fix(model): improve wrong alias error message [#10041](https://github.com/sequelize/sequelize/pull/10041)
- feat(sqlite): CITEXT datatype [#10036](https://github.com/sequelize/sequelize/pull/10036)
- fix(postgres): remove if not exists and cascade from create/drop database queries [#10033](https://github.com/sequelize/sequelize/pull/10033)
- fix(postgres): remove if not exists and cascade from create/drop database queries [#10033](https://github.com/sequelize/sequelize/pull/10033)
- fix(syntax): correct parentheses around union [#10003](https://github.com/sequelize/sequelize/pull/10003)
- feat(query-interface): createDatabase / dropDatabase support [#10027](https://github.com/sequelize/sequelize/pull/10027)
- feat(postgres): CITEXT datatype [#10024](https://github.com/sequelize/sequelize/pull/10024)
......@@ -356,7 +353,6 @@ dialectOptions: {
- fix(destroy): attributes updated in a beforeDestroy hook are now persisted on soft delete [#9319](https://github.com/sequelize/sequelize/pull/9319)
- fix(addScope): only throw when defaultScope is defined [#9703](https://github.com/sequelize/sequelize/pull/9703)
### 5.0.0-beta.10
- fix(belongsToMany): association.add returns array of array of through records [#9700](https://github.com/sequelize/sequelize/pull/9700)
......@@ -373,7 +369,6 @@ dialectOptions: {
- feat(model): column level comments [#9573](https://github.com/sequelize/sequelize/pull/9573)
- docs: cleanup / correct jsdoc references [#9702](https://github.com/sequelize/sequelize/pull/9702)
### 5.0.0-beta.9
- fix(model): ignore undefined values in update payload [#9587](https://github.com/sequelize/sequelize/pull/9587)
......
......@@ -7,6 +7,7 @@ const sequelize = new Sequelize('database', 'username', 'password', {
dialect: 'mysql'
});
```
This will save the passed database credentials and provide all further methods.
Furthermore you can specify a non-default host/port:
......@@ -57,14 +58,14 @@ const sequelize = new Sequelize('database', 'username', 'password', {
// for postgres, you can also specify an absolute path to a directory
// containing a UNIX socket to connect over
// host: '/sockets/psql_sockets'.
 
// custom port; default: dialect default
port: 12345,
 
// custom protocol; default: 'tcp'
// postgres only, useful for Heroku
protocol: null,
 
// disable logging; default: console.log
logging: false,
......@@ -76,20 +77,20 @@ const sequelize = new Sequelize('database', 'username', 'password', {
supportBigNumbers: true,
bigNumberStrings: true
},
 
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite',
 
// disable inserting undefined values as NULL
// - default: false
omitNull: true,
 
// a flag for using a native library or not.
// in the case of 'pg' -- set this to true will allow SSL support
// - default: false
native: true,
 
// Specify options, which are used when sequelize.define is called.
// The following example:
// define: { timestamps: false }
......@@ -106,10 +107,10 @@ const sequelize = new Sequelize('database', 'username', 'password', {
},
timestamps: true
},
 
// similar for sync: you can define this to always force sync for models
sync: { force: true },
 
// pool configuration used to pool database connections
pool: {
max: 5,
......@@ -184,6 +185,7 @@ const sequelize = new Sequelize('database', 'username', 'password', {
```
or using connection String:
```js
const sequelize = new Sequelize('mariadb://user:password@example.com:9821/database')
```
......@@ -196,7 +198,7 @@ For SQLite compatibility you'll need`sqlite3@^4.0.0`. Configure Sequelize like t
const sequelize = new Sequelize('database', 'username', 'password', {
// sqlite! now!
dialect: 'sqlite',
 
// the storage engine for sqlite
// - default ':memory:'
storage: 'path/to/database.sqlite'
......@@ -306,8 +308,8 @@ named parameters (starting with `:`), or unnamed, represented by a ?
The syntax used depends on the replacements option passed to the function:
* If an array is passed, `?` will be replaced in the order that they appear in the array
* If an object is passed, `:key` will be replaced with the keys from that object.
- If an array is passed, `?` will be replaced in the order that they appear in the array
- If an object is passed, `:key` will be replaced with the keys from that object.
If the object contains keys not found in the query or vice versa, an exception
will be thrown.
......@@ -349,7 +351,6 @@ sequelize.query('select 1 as `foo.bar.baz`').then(rows => {
})
```
[0]: /manual/usage.html#options
[1]: /manual/models-definition.html#configuration
[2]: /class/lib/sequelize.js~Sequelize.html
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!