Sequelize, Node.js и PostgreSQL: примеры использования ORM
Технический директор компании vverh.digital. JavaScript программист, любитель Kotlin и Swift. Когда начинаешь делать очередной проект, появляется желание упростить себе жизнь и лишний раз не писать SQL-запросы. В таком случае было бы неплохо познакомиться с технологией ORM. ORM – (с англ. Object-Relational Mapping, объектно-реляционное отображение) технология в программировании, которая связывает ваши объекты с базой данных, тем самым создавая виртуальную базу данных. К виртуальной базе данных можно обращаться, извлекая или записывая информацию без написания SQL-запросов. Sequelize – это Node.js ORM на базе промисов, которая может работать в связке Postgres, MySQL, MariaDB, SQLite, Microsoft SQL Server, Amazon Redshift. Sequelize может помочь закрыть 90% нужных задач без написания SQL-запросов. Внутри есть поддержка создания, обновления, удаления сущностей. Есть поддержка вложенных сортировок, сложных условий, LEFT JOIN, лимитов, подзапросов, кастомных запросов, а также есть защита от SQL-инъекций и отмена транзакций. Как базу данных мы будем использовать PostgreSQL, поэтому пример интеграции Sequelize в проект будем показывать на ней. С вас готовый Node.js-сервер (можно с express) и развернутая база данных. Для начала, установим Sequelize командой: После этого устанавливаем «драйверы» для ORM: Если вы пожелаете использовать MySQL вместо Postgres, то вам надо установить другие пакеты: Подробней про это можно почитать тут. Подключайте базу данных в основном файле проекта (это может быть app.js). app.js db.js После запуска вы должны увидеть в консоли Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека фронтендера» Интересно, перейти к каналу У Sequelize есть множество методов, которые позволяют удобно взаимодействовать с базой данных. Но перед тем как начать их рассматривать, нам нужно сделать некоторые подготовительные работы. Для начала давайте создадим таблицу Теперь нам нужно создать нужный класс модели в нашем проекте. Для этого создайте папку Теперь импортируйте в нужное место и используйте по назначению. Для примера. Если какие-то поля в описании модели имеют Если хотите указать лимит, то можно добавить атрибуты А если хотите получить какие-то конкретные поля (а не все), то достаточно указать аргумент Если хотите все отсортировать, достаточно указать атрибут Кроме Для сложных условий существует оператор Или Все. Но лишь бы не Поиск через В MySQL нет оператора Прибавить 1 к полю Убавить 1 от поля Можно связать с моделью, сделав свой собственный метод и вызывать его через Чтобы делать Таблица files в базе данных. И не забудем добавить Теперь надо добавить связь в ORM класс: Главное – выше не забудьте внутрь одной модели импортировать другую модель. После этого в нужном месте делаете так: Результат вас должен приятно удивить: У автора стоит плагин для Google Chrome JSON Viewer Можно делать Показанным способом вы можете отменять транзакции в базе данных. Главное – не забывайте использовать *** В этой статье мы рассмотрели потрясающую ORM для Node.js – Sequelize. Мы научились: Максим Колмогоров
Что такое ORM
Что такое Sequelize
Установка и настройка
npm install sequelize
npm install pg pg-hstore
npm install --save mysql2
const db = require('./db.js') db.authenticate() .catch(error => console.error(error))
const Sequilize = require('sequelize') module.exports = new Sequilize('proglib', 'postgres', 'secret', { host: 'localhost', dialect: 'postgres', operatorsAliases: 0, pool: { max: 5, min: 0, acquire: 3000, idle: 10000 } })
SELECT 1+1 AS result
. Это значит, что подключение прошло успешно:Методы
Создание таблицы в базе и ORM класса в проекте
users
в базе данных, а после ORM класс в Node.js для взаимодействия с ней:models
и добавьте там файл users.js
. Добавьте в файл этот код:
// Db const { DataTypes } = require('sequelize') const db = require('../db.js') const Users = db.define('users', // Описание таблиц { user_id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false }, firstname: { type: DataTypes.STRING, allowNull: false }, lastname: { type: DataTypes.STRING, allowNull: false }, comment: { type: DataTypes.TEXT, allowNull: true }, order_by: { type: DataTypes.INTEGER, allowNull: false }, file_id: { type: DataTypes.INTEGER, allowNull: true } }, // Опции { timestamps: false } ) module.exports = Users
Создание элемента
const Users = require('./models/users.js') await Users.create({ firstname: 'Иван', lastname: 'Иванов', comment: 'Классный парень', order_by: 10 })
allowNull: false
, и вы попытаетесь создать сущность без них, то фреймворк выдаст ошибку.Обновление элемента
const Users = require('./models/users.js') await Users.update({ firstname: 'Сергей' }, { where: { user_id: 1 } })
Удаление элемента
const Users = require('./models/users.js') await Users.destroy({ where: { user_id: 1 } })
Найти один элемент
const Users = require('./models/users.js') const user = await Users.findOne({ where: { user_id: 1 } })
Найти много элементов
const Users = require('./models/users.js') const user = await Users.findAll({ where: { order_by: 10 } })
offset
и limit
к аргументам объекта:
const Users = require('./models/users.js') const user = await Users.findAll({ where: { order_by: 10 }, offset: 0, limit: 10 })
attributes
и передать туда массив с нужными полями:
const Users = require('./models/users.js') const user = await Users.findAll({ attributes: ['firstname', 'lastname', 'order_by'], where: { order_by: 10 }, offset: 0, limit: 10 })
order
и указать, какую сортировку будем делать и по какому полю:
const Users = require('./models/users.js') const user = await Users.findAll({ attributes: ['firstname', 'lastname', 'order_by'], where: { order_by: 10 }, offset: 0, limit: 10, order: [ ['order_by', 'ASC'] ] })
ASC
(по возрастанию) можно указать DESC
(по убыванию).Сложные условия
Op
. Он поддерживает множество конструкций, например: and
, or
, not in
, in
, like
, between
, not between
, регулярные выражения. Давайте продемонстрируем парочку примеров.order_by
равно 10 или user_id
равно 1:
const { Op } = require('sequelize') const Users = require('./models/users.js') const user = await Users.findAll({ where: { [Op.or]: { order_by: 10, user_id: 1 } } })
user_id
под номером 1:
const { Op } = require('sequelize') const Users = require('./models/users.js') const user = await Users.findAll({ where: { user_id: { [Op.notIn]: [1] } } })
iLike
:
const { Op } = require('sequelize') const Users = require('./models/users.js') const user = await Users.findAll({ where: { name: { [Op.iLike]: `%Иван%` } } })
iLike
, надо использовать like
. Разница лишь в поиске с учетом регистра и без.Инкремент и декремент
order_by
:
const Users = require('./models/users.js') await Users.increment('order_by', { by: 1, where: { user_id: 1 } })
order_by
:
const Users = require('./models/users.js') await Users.decrement('order_by', { by: 1, where: { user_id: 1 } })
Кастомные запросы
const db = require('./db.js') await db.query('SELECT * FROM users')
model.myMethod()
. Для этого нужно просто добавить метод в модель таким способом:Связи
LEFT JOIN
и тянуть данные из связанных таблиц полезно сделать связь. Для этого давайте создадим таблицу files
в базе данных с полями file_id
, path
. И забьем ее данными:file_id
к нужным пользователям в таблице users
:
Users.hasOne(Files, { foreignKey: 'file_id', sourceKey: 'file_id', as: 'file_info' }) Files.belongsTo(Users, { foreignKey: 'file_id', targetKey: 'file_id', as: 'file_info' })
const Users = require('./models/users.js') const Files = require('./models/files.js') const result = await Users.findOne({ include: [ { model: Files, as: 'file_info' } ], where: { user_id: 1 } })
include
с «обратной» стороны, если вы сделали belongsTo
. Это значит, что можно делать include
не только из основного класса, но и дополнительного (с кем связались через belongsTo
). В нашем случае из класса Files
. Также, кроме hasOne
есть еще hasMany
для «подгрузки» множества элементов.Отмена транзакции
const Users = require('./models/users.js') const transaction = await Users.sequelize.transaction() const result = await Users.create({ firstname: 'Иван', lastname: 'Иванов', comment: 'Классный парень', order_by: 10 }, { transaction }) if (result.user_id > 25) { await transaction.rollback() } else { await transaction.commit() }
commit()
для подтверждения транзакции и rollback()
для ее отмены.Материалы по теме
- 0 views
- 0 Comment