Returning a Model Instance and Quyerying Again Sequelize
Creating Sequelize Associations with the Sequelize CLI
Sequelize is a popular, like shooting fish in a barrel-to-use JavaScript object relational mapping (ORM) tool that works with SQL databases. It'due south fairly straightforward to offset a new project using the Sequelize CLI, but to truly take advantage of Sequelize'due south capabilities, you'll want to define relationships betwixt your models.
In this walkthrough, nosotros'll set up a Sequelize project to assign tasks to particular users. We'll utilize associations to ascertain that human relationship, and so explore ways to query the database based on those associations.
Let's start by installing Postgres, Sequelize, and the Sequelize CLI in a new project binder:
mkdir sequelize-associations
cd sequelize-associations
npm init -y
npm install sequelize pg
npm install --salvage-dev sequelize-cli
Next, let's initialize a Sequelize project, so open up the whole directory in our lawmaking editor:
npx sequelize-cli init
lawmaking .
To learn more well-nigh whatsoever of the Sequelize CLI commands below, run across:
Getting Started with Sequelize CLI
Let'south configure our Sequelize project to work with Postgres. Discover config.json
in the /config
directory and supercede what'due south there with this code:
{
"development": {
"database": "sequelize_associations_development",
"host": "127.0.0.1",
"dialect": "postgres"
},
"exam": {
"database": "sequelize_associations_test",
"host": "127.0.0.1",
"dialect": "postgres"
},
"product": {
"database": "sequelize_associations_production",
"host": "127.0.0.one",
"dialect": "postgres"
}
}
Cool, at present nosotros can tell Sequelize to create the database:
npx sequelize-cli db:create
Next we volition create a User
model from the command line:
npx sequelize-cli model:generate --name User --attributes firstName:cord,lastName:string,electronic mail:string,password:string
Running model:generate
automatically creates both a model file and a migration with the attributes nosotros've specified. You tin notice these files within your project directory, only there's no need to change them right at present. (Later, we'll edit the model file to define our associations.)
Now we'll execute our migration to create the Users
table in our database:
npx sequelize-cli db:migrate
Now let's create a seed file:
npx sequelize-cli seed:generate --proper name user
You will see a new file in /seeders
. In that file, paste the following code to create a "John Doe" demo user:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('Users', [{
firstName: 'John',
lastName: 'Doe',
e-mail: 'demo@demo.com',
password: '$321!pass!123$',
createdAt: new Engagement(),
updatedAt: new Date()
}], {});
}, down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete('Users', null, {});
}
};
Once we've saved our seed file, allow's execute it:
npx sequelize-cli db:seed:all
Driblet into psql
and query the database to see the Users
table:
psql sequelize_associations_development
SELECT * FROM "Users";
Defining associations
Peachy! We've got a working User
model, but our John Doe seems a little bored. Let's give John something to do by creating a Chore
model:
npx sequelize-cli model:generate --name Job --attributes title:cord,userId:integer
Just as with the User
model higher up, this Sequelize CLI control will create both a model file and a migration based on the attributes we specified. Just this time, we'll demand to edit both in order to necktie our models together.
First, notice task.js
in the /models
subdirectory within your projection directory. This is the Sequelize model for tasks, and you'll see that the sequelize.define()
method sets up title
and userId
equally attributes, but as we specified above.
Below that, you'll run across Chore.associate
. It's currently empty, but this is where we'll really tie each task to a userId
. Edit your file to await like this:
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.ascertain('Task', {
championship: DataTypes.STRING,
userId: DataTypes.INTEGER
}, {});
Chore.associate = function(models) {
// associations can be defined hither
Chore.belongsTo(models.User, {
foreignKey: 'userId',
onDelete: 'CASCADE'
})
};
return Task;
};
What do those changes exercise? Task.belongsTo()
sets upwardly a "belongs to" relationship with the User
model, meaning that each task volition be associated with a specific user.
We do this by setting userId
as a "strange key," which means it refers to a key in another model. In our model, tasks must belong to a user, and then userId
will correspond to theid
in a particular User
entry. (The onDelete: 'CASCADE'
configures our model then that if a user is deleted, the user'south tasks will exist deleted too.)
We also need to change our User
model to reflect the other side of this human relationship. Find user.js
and change the department under User.acquaintance
so that your file looks similar this:
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
firstName: DataTypes.Cord,
lastName: DataTypes.STRING,
password: DataTypes.Cord,
email: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
User.hasMany(models.Task, {
foreignKey: 'userId',
})
};
return User;
};
For this model, nosotros've set upward a "has many" relationship, meaning a user can accept multiple tasks. In the .hasMany()
method, the foreignKey
option is set to the name of the key on the other table. In other words, when theuserId
on a job is the same equally the id
of a user, we have a match.
Nosotros still have to brand one more than change to set up our relationship in the database. In your project's/migrations
folder, you should see a file whose proper noun ends with create-task.js
. Change the object labeled userId
so that your file looks like the code below:
module.exports = {
upward: (queryInterface, Sequelize) => {
render queryInterface.createTable('Tasks', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
blazon: Sequelize.String
},
userId: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Users',
key: 'id',
as: 'userId',
}
},
createdAt: {
allowNull: false,
type: Sequelize.Date
},
updatedAt: {
allowNull: imitation,
type: Sequelize.DATE
}
});
},
downward: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Tasks');
}
};
The references
section will prepare up the Tasks
table in our database to reflect the same relationships we described above. Now we can run our migration:
npx sequelize-cli db:migrate
At present our John Doe is ready to take on tasks — but John notwithstanding doesn't have any actual tasks assigned. Allow'south create a task seed file:
npx sequelize-cli seed:generate --name task
Find the newly generated seed file and paste in the following to create a task:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('Tasks', [{
title: 'Build an app',
userId: 1,
createdAt: new Date(),
updatedAt: new Date()
}], {});
}, down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete('Tasks', cypher, {});
}
};
We'll gear up userId
to 1
so that the chore will belong to the user we created earlier. Now we tin can populate the database.
npx sequelize-cli db:seed:all
Test the database:
psql sequelize_associations_development
SELECT * FROM "Users" JOIN "Tasks" ON "Tasks"."userId" = "Users".id;
Querying via Sequelize
At present nosotros tin query our database for data based on these associations — and through Sequelize, we can practice it with JavaScript, which makes it piece of cake to comprise with a Node.js application. Let's create a file to hold our queries:
affect query.js
Paste the lawmaking below into your new file:
const { User, Task } = require('./models')
const Sequelize = require('sequelize');
const Op = Sequelize.Op// Detect all users with their associated tasks
// Raw SQL: SELECT * FROM "Users" Bring together "Tasks" ON "Tasks"."userId" = "Users".id;
const findAllWithTasks = async () => {
const users = await User.findAll({
include: [{
model: Chore
}]
});
console.log("All users with their associated tasks:", JSON.stringify(users, nix, four));
}
const run = async () => {
await findAllWithTasks()
await process.exit()
}
run()
The first three lines above import our User
and Job
models, along with Sequelize. Afterward that, we include a query office that returns every User
along with that user'southward associated tasks.
Sequelize's .findAll()
method accepts options as a JavaScript object. Above, we used the include
option to have advantage of "eager loading" — querying data from multiple models at the same time. With this selection, Sequelize will return a JavaScript object that includes each User
with all associated Job
instances as nested objects.
Let's run our query file to run into this in action:
node query.js
Now it'due south articulate that our John Doe has a project to work on! We can use the same method to include the User
when our query finds a Task
. Paste the post-obit lawmaking into query.js
:
// Find a task with its associated user
// Raw SQL: SELECT * FROM "Tasks" Join "Users" ON "Users"."id" = "Tasks"."userId";const findTasksWithUser = async () => {
const tasks = await Job.findAll({
include: [{
model: User
}]
});
console.log("All tasks with their associated user:", JSON.stringify(tasks, naught, 4));
}
Alter const run
at the bottom of query.js
by adding a line to telephone call findTasksWithUser()
. Now run your file again in Node — each Job
should include info for the User
it belongs to.
The queries in this walkthrough make use of the
.findAll()
method. To learn more about other Sequelize queries, see: Using the Sequelize CLI and Querying
You can as well include other options aslope include
to make more than specific queries. For example, below we'll use the where
choice to find but the users named John while still returning the associated tasks for each:
// Find all users named John with their associated tasks
// Raw SQL: SELECT * FROM "Users" WHERE firstName = "John" Join tasks ON "Tasks"."userId" = "Users".id; const findAllJohnsWithTasks = async () => {
const users = await User.findAll({
where: { firstName: "John" },
include: [{
model: Chore
}]
});
console.log("All users named John with their associated tasks:", JSON.stringify(users, null, iv));
}
Paste the above into your query.js
and modify const run
to call findAllJohnsWithTasks()
to try it out.
Now that you know how to apply model associations in Sequelize, you tin design your awarding to deliver the nested data you need. For your next step, you might decide to include more robust seed data using Faker or integrate your Sequelize application with Express to create a Node.js server!
This article was co-authored with Jeremy Rose, a software engineer, editor, and writer based in New York City.
More than info on Sequelize CLI:
- Getting Started with Sequelize CLI
- Using Sequelize CLI and Querying
- Sequelize CLI and Express
- Getting Started with Sequelize CLI using Faker
- Build an Express API with Sequelize CLI and Express Router
- Building an Express API with Sequelize CLI and Unit of measurement Testing!
Resource
- https://sequelize.org/principal/manual/associations.html
- https://sequelize.org/principal/manual/querying.html
Source: https://levelup.gitconnected.com/creating-sequelize-associations-with-the-sequelize-cli-tool-d83caa902233
ارسال یک نظر for "Returning a Model Instance and Quyerying Again Sequelize"