This tutorial is out of date and no longer maintained.
In this tutorial, we will be creating an AngularJS application with Sequelize in a three-part series broken down as follows:
Part 1 - Creating out the server-side of our sample application with Node.js and PostgreSQL with Sequelize. Part 2 - Creating a front end for the application in AngularJS and Angular Material. Part 3 - Testing and Deploying to Heroku.
Object Relational Mapping (ORM) is popular in most Object-Oriented Programming languages as a way of designing and querying relational databases by representing relational data as objects.
Some of the widely used ORMs are:
While most javascript frameworks have a bias for the NoSQL JavaScript-based MongoDB, other databases such as PostgreSQL and MySQL are still very popular.
Beginner knowledge and inital setup on your local environment will be required using the following:
Sequelize supports a variety of database engines such as PostgreSQL, MySQL, Microsoft SQL Server, SQLite, and MariaDB. Being an ORM, Sequelize does not support NoSQL databases such as MongoDB and CouchDB.
Sequelize enables you to access your data from your business logic with a uniform API for performing CRUD operations as opposed to dealing with the length SQL statements. This is obviously bound to make the development of your applications faster and painless. You can, however, still run your own custom SQL statements on Sequelize if it does not meet your needs.
Sequelize also supports migrations, which is like a version control for your database
Sequelize also automatically escapes user input and therefore helps to avoid SQL injection on your behalf.
Despite all the good things that can be said about Sequelize, there is a learning curve that comes along with adopting it and the documentation can be quite overwhelming. We will be looking at a very neat and very concise way of getting things up and running with Sequelize.
Bookmark is an author management application that stores the details of an author as well as the details of all the books that they have written.
Bookmark should allow us to perform actions such as:
This simple application should be enough to get our hands dirty with CRUD operations using Sequelize and work with relationships between PostgreSQL tables.
The bookmark application directory structure will look like this.
├── index.js
├── gulpfile.js
├── package.json
├── bower.json
├── .bowerrc
├── .sequelizerc
├── app/
├── images/
├── js/
├── styles/
├── views/
├── app.js
├── index.jade
├── server/
├── config/
├──config.js
├── controllers/
├── authors.js
├── books.js
├── migrations/
├── models/
├── index.js
├── book.js
├── author.js
├── seeders/
To get started, we will need to add the PostgresSQL client for JavaScript to our dependencies.
Next, we will add a .sequelizerc
file that contains our sequelize default configurations.
Run the sequelize initialization command to get our sequelize bootstrap started. If it does not work, refer to the sequelize CLI module documentation and make sure it is properly set up for your environment.
This should create a few directories in our server directory:
config.json
file from which the database details will be read from. To use the environment variables which are also supported, we will be using config.js
instead.index.js
file inside models that loads all the models that we add to this directory. Be sure to update models/index.js
to read config variables from the config/config.js
file as opposed to reading from the default config/config.json
.We mentioned that we will replace the config.json
file with config.js
file and populate it with the database credentials as follows:
Notice that we can use the username, password format, or URL format to create a connection to the database. I prefer the URL as it is shorter. The dialect specifies the database driver we will be using. In this case, it will be Postgres.
Be sure to update server/models/index.js
to create the connection using the URL.
Once we have the project set up, proceed to create a PostgreSQL database called bookmark
.
We can then test to see if the connection to the database was successful using the authenticate()
method.
Simply add the following code in index.js
.
Once we have our project set up and have verified our connection to the database, let’s proceed to create our first model and migration in the server directory.
A map between the model and the database table is done using the define
method which takes in the table name as a parameter, an attributes object, and an options attribute.
Fortunately, the Sequelize CLI tool provides us with a very handy command-line tool to create a model and migration all in one command. Simply run:
This will add the following files to our application:
server/models/author.js
server/migrations/2016..-create-author.js
The --underscored
parameter specifies that we would like our timestamp fields (created_at
and updated_at
) to appear in the underscore format. Notice that the author model does not have the underscored
attribute option so it still expects our timestamps to be createdAt
and updatedAt
. Let’s fix that.
The author model will then give us access to methods such as findAll()
, create()
, update()
and destroy()
.
In the previous section, we were able to create a connection to the bookmark database and create a model and migrations for the Authors
table.
This means that our table does not exist yet. Running the migrations is just as easy. Simply run sequelize db:migrate
This will add an empty Authors
table and another SequelizeMeta
to keep track of the migrations.
Now that we have a model and a table to query data from, we will proceed to create the CRUD operations from which our front end will be able to query.
Create a server/controllers
directory and add an authors.js
file to hold our query methods. We will create methods to perform the following actions:
index()
- List of all authors using the findAll()
method which takes optional parameters such as attributes, where filters, Pagination/Limits, data ordering, and Relations/Associations. Read more about querying options here.show()
- Details about one author using the findById()
method takes in an id to get a record by.create()
- Add a new author using the create()
method which takes in an array of the record to create.update()
- Modify existing author details using the update()
method which takes an array of the data to update, and a where
object to filter records to update.delete()
- Delete an author from the platform using the destroy()
method which takes an object of parameters inside a where
object.Each of these methods from the Author model returns a promise which we then use to return a 200 status code message and the queried data. If an error occurs, we catch the error and return a 500 status code to the front end.
Database tables often relate to data in other tables. In our case, an author can have many books. But each book can only belong to one user. This presents a One to Many
relationship. Let’s take a minute to look at how Sequelize implements database relationships.
One-To-One associations are associations between exactly two models connected by a single foreign key.
This is the most basic form of relationship where an entity, say a User may only have one relationship to another entity, say Phone and the reverse holds true that a Phone belongs to only one user.
One-To-One association is achieved using belongsTo()
and hasOne()
methods. Both can be used in different cases by setting one as the source and the other as the target.
In the example below, the Phone model acts as the source and the User model acts as the target.
One-To-Many comes into play when one source, in our case Author, has multiple targets, say Books. This is achieved using the hasMany()
method which we will be looking at as we set up the Books model.
This will add a author_id
foreign key field in our case or authorId
if underscored
is set to false.
One-To-Many association is used when multiple sources are linked to multiple targets. In our application, this could be many books can have many genres and many genres can also belong to many books.
This will add a new pivot table BookGenre
that has book_id
and genre_id
foreign keys. You can also rename your Model and define the foreign key names in the many-to-many relationship.
This adds additional methods to both the Book and Genre models that make it easy to query data.
getGenres
and addGenre
setBooks
and getBooks
Our bookmark application does not have a many-to-many relation between Books and Genres. Can you challenge yourself to add this relation?
To create this relation, we will need to create the books model and migration first. We have already gone through how to create both for Authors. Can you challenge yourself to create the Books model?
Here is the sequelize CLI command to create the model and migration. Our Book will have the book name, ISBN number, publication date, description id, and the author id.
Update the new Book model to use snake_case
for the timestamps using the underscored
attribute.
Next, we will add the association in the classMethods
object defined in our Author model. onDelete: 'cascade'
guarantees that when an author is deleted, the attached books are deleted as well.
We do not need to specify the author_id
foreign key because this is the default key the Author model expects. The last thing we need to do is see the relation in action! But how do we do this?
Remember the Author controller we created earlier? We can now return an author with the list of all the books under their name by adding the include
option in findById
for the show()
method and findAll
for the index method.
When our frontend makes a GET request to index or show, the returned request will contain an array of books (Empty since we do not have the books controller up and running yet).
Start a Node.js server using express on your localhost in index.js
and call the index method when a GET request is made to /authors
. You can then use postman to make the request since we do not have a front end to consume our controller methods.
Let’s go ahead and add the CRUD operations to query data from the Books model. We will be using the exact approach we used for servers/controllers/authors.js
. Are you up for the challenge?
Here is an excerpt of how servers/controllers/books.js
looks like.
The last part of this tutorial involves adding the API endpoints from which our front end will be able to query data from. Since our app is simple, we will simply add them in index.js
:
Once we add a sample user and book to our bookmark database, go ahead and make a GET request to /authors
. This time we should have a sample book on the author
response.
In this article, we were able to achieve the following:
We also threw in a few challenges that should help you explore Sequelize further. In the second part, we will create a simple frontend using Angular and Angular Material.
While this has been a gentle introduction to Sequelize, there is a lot more to learn. Feel free to engage in the comment section.
You can also follow what we have been doing on the GitHub repo for bookmark.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!