Sequelize is a promise-based ORM for Node.
Example
1 | const Sequelize = require('sequelize') |
Start
Installation
1 | yarn add sequelize |
Setup a connection
Sequelize will setup a connection pool on initialization so you should ideally only ever create one instance per database if you’re connecting to the DB from a single process. If you’re connecting to the DB from multiple processes, you’ll have to create one instance per process, but each instance should have a maximum connection pool size of “max connection pool size divided by number of instances”. So, if you wanted a max connection pool size of 90 and you have 3 worker process, each process’s instance should have a max connection pool size of 30.
1 | const Conn = new Sequelize('database', 'username', 'password', { |
Test the connection
You can use the .authenticate()
function like this to test the connection.
1 | Conn.authenticate().then(() => { |
Model
Models are defined with Conn.define('name', {attributes}, {options})
1 | const User = Conn.define('user', { |
Query
1 | User.findAll().then(users => { |
Application wide model options
The Sequelize constructor takes a define
option which will be used as the default options for all defined models.
1 | const Conn = new Sequelize('connectionUri', { |
Promises
Sequelize uses promises to control async control-flow.
Basically, a promise represents a value which will be present at some point.
1 | user = await User.fineOne() |
Model Definition
To define mapping between a model and a table, use the define
method. Sequelize will then automatically add the attributes createdAt
and updatedAt
to it. So you will be able to know when the database entry went into the db and when it was updated the last time.
1 | const Project = Conn.define('project', { |
You can also set some options on each column:
1 | const Foo = Conn.define('foo', { |
Configuration
You can also influence the way Sequelize hadnles your column names:
1 | const Bar = Conn.define('bar', { |
Import
You can also store your model definitions in a single file using the import
method. The returned object is exactly the same as defined in the imported file’s function.
1 | // in your server file |
The import
method can also accept a callback as an argument
1 | Conn.import('project', (Conn, DataTypes) => { |
Database Synchronization
When starting a new project you won’t have a database structure and using sequelize you won’t need to. Just specify your model structures and let the library do the rest. Currently supported is the creation and deletion of tables.
1 | // Create the Tables |
Because synchronizing and dropping all of your tables might be a lot of lines to write, you can also let Sequelize do the work for you:
1 | // sync all models that aren't already in the database |
Expansion of models
Sequelize Models are ES6 classes, you can very easily add custom instance or class level methods.
1 | const User = Conn.define('user', { |
Indexes
Sequelize supports adding indexes to the model definition which will be created during Model.sync()
or Conn.sync()
1 | Conn.define('user', {}, { |
Model Usage
Data Retrieval / Finders
Finder methods are intended to query data from the database. They do not return plain objects but instead return model instances. Because finder methods return model instances you can call any model instance member.
find - search for one specific element in the database
1 | // search for known id |
findOrCreate - Search for a specific element or create it if not available
The method findOrCreate
can be used to check if a certain element already exists in the database. If that is the case the method will result in a respective instance, if the element does not yet exists, it will be created.
Let’s assume we have an empty database with a User
model which has a username
and a job
1 | User.findOrCreate({ |
The code created a new instance.
fineAndCountAll - Search for multiple elements in the database, returns both data and total count
findAll - Search for multiple elements in the database
1 | // find multiple entries |
Complex filtering /OR/NOT queries
1 | Project.findAll({ |
Both pieces of code will generate the following:
1 | SELECT * FROM `Projects` WHERE ( |
Manipulating the database with limit, offset, order and group
1 | // limit the results of the query |
The syntax for grouping and ordering are equal, so below it is only explained with a single example for group, and the rest for order.
1 | // yields ORDER BY title DESC |
Raw queries
Sometimes you might be expecting a massive dataset that you just want to display without manipulation. For each row you select, Sequelize creates an instance with functions for update, delete, get association etc. If you have thousands of rows, this might take some time. If you only need the raw data and don’t want to update anything, you can do like this to get the raw data.
1 | // Are you expecting a massive dataset from the DB, and don't want to spend the time building DAOs for each entry? You can pass an extra query option to get the raw data insetead: |
Queries
Attributes
To select only some attributes, you can use the attributes
option. Most often, you pass an array:
1 | Model.findAll({ |
Where
Whether you are querying with findAll
/find
or doing bulk updates
/destroy
you can pass a where
object to filte the query.
where
generally takes an object from attribute:value pairs, where value can be primitive for equality matches or keyed objects for other operators.
It’s also possible to generate complex AND
/OR
conditions by nesting of $or
and $and