Как упростить работу с базами данных в Node.js с помощью Objection.js

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Objection.js — сравнительно молодая и минималистичная ORM-библиотека для Node.js, которая сильно упрощает взаимодействие с базами данных и не перегружена дополнительными функциями, как sequalize или typeORM. Разбираемся, в чем ее специфика и как строить запросы с ее помощью.

Это адаптированный перевод статьи A Step Towards Simplified Querying in NodeJS из блога компании Velotio Technologies. Повествование ведется от лица автора оригинала.

Недавно я увидел на StackOverflow историю разработчика, который столкнулся с проблемой использования ORM. Этот кейс натолкнул меня на мысль написать статью о альтернативе sequelize — Objection.js, библиотеке, которая решает множество проблем ORM.

Что такое ORM

ORM или метод реляционного сопоставления объектов — решениe для сопоставления объектов в программе с таблицами базы данных. Он позволяет разработчикам взаимодействовать с объектами вместо того, чтобы писать запросы к базе данных.

ORM позволяет строить динамические запросы с помощью Query Builder и абстрагироваться от особенностей конкретной базы данных. Решения обычно поддерживают Postgres, MySQL, SQLite и другие базы данных.

Вопрос на StackOverflow касался преобразования приведенного ниже запроса в sequelize-запрос. Стоит отметить, что его писал начинающий разработчик:

Решение на sequelize выглядит так:

Учитывая простоту запроса, решение кажется сложным, и чем больше в нем новых отношений, тем оно сложнее. Такие простые запросы в sequelize описаны недостаточно подробно.

Для сравнения разберем, как решение задачи будет выглядеть на Objection.js:

Буду честен — я сам пользуюсь Objection.js, что не делает его лучшим ORM для NodeJS. Каждая библиотека имеет свою специфику, а некоторые разработчики вообще выступают против любых ORM и предлагают вручную писать SQL-запросы. Отчасти они правы. Если ваше приложение достаточно маленькое, и вы можете написать несколько функций-хелперов для выполнения запросов, то используйте обычный SQL вместо ORM.

ORM нужна, когда в приложении много таблиц с большим количеством связей, которые нужно определить, и выполнить несколько объединенных запросов.

Список самых упоминаемых ORM для NodeJS выглядит так:

  1. Sequelize

  2. Objection.js

  3. typeORM

Почему я выбрал Objection.js

  1. В основе решения — мощный конструктор SQL-запросов KNEX.JS.

  2. Библиотека позволяет выполнять запросы через функции async/await.

  3. Позволяет добавить валидацию с помощью JSON схемы.

  4. Позволяет создавать модели для таблиц с использованием синтаксиса ES6/ES7 и определять связи между ними.

  5. Objection.js автоматически строит связи между объектами и самостоятельно определяет, какие данные нужно сохранить, а какие — обновить (за это отвечают функции upsert и insert).

У Objection.js и KNEX.JS очень понятная и обширная документация, в которой легко найти инструкции и примеры использования. В официальном репозитории библиотеки на GitHub есть множество примеров использования библиотеки и подробная инструкция по ее установке и настройке.

Создание и управление схемой базы данных

Миграция — один из подходов к внесению изменений в базу данных, в этой статье сосредоточимся на нем. В Objection.js используются механизмы миграции KNEX.JS. Поскольку речь идет об ORM, определять таблицы и столбцы можно не с помощью SQL, а непосредственно написанием кода на JavaScript. Для создания новой миграции выполним команду KNEX CLI:

После выполнения этой команды в каталоге миграций появится новый файл с текущей временной меткой и именем, которое мы присвоили этой миграции. Выглядит он следующим образом:

Функция exports.up определяет команды, выполнение которых внесет нужны изменения в базу данных. Например, речь может идти о создании таблиц базы данных, добавлении или удалении столбца из таблицы, изменении индексов и других действиях.

Вторая функция, exports.down, выполняет противоположные первой действия: например, когда exports.up создает таблицу, exports.down удаляет ее. Она нужна для того, чтобы быстро откатить изменения, сделанные миграцией, если это потребуется.

В случае ниже в функции upсоздается таблица persons с необходимыми столбцами и индексами, а в функции down таблица удаляется, если она существует:

Запустить процесс миграции можно следующим образом:

Также можно передать флаг — env или установить NODE_ENV, чтобы выбрать альтернативную среду:

Модели

Модели базы данных — абстракции вокруг таблиц базы данных, которые помогают инкапсулировать бизнес-логику внутри них. В Objection.js модели можно создавать c помощью классов ES.

Прежде чем продолжить, уточним, что модели в Objection.js не создают таблиц в базах данных, а предназначены для добавления валидаций и создания связей между моделями. Например:

В этом коде есть три статистических геттера. Первый, tableName, возвращает имя таблицы.

Второй, jsonSchema, определяет параметры валидации каждого поля. В нем можно указать необходимые свойства: например, тип поля (число, строку, объект и тд).

Третий, relationMappings, определяет связь выбранной модели с другими моделями. В данном случае ключ внешнего объекта pets — ссылка на связанный класс. Свойство join определяет, как модели связаны друг с другом, а from и to объекта join определяют поля базы данных, с помощью которых связаны модели. Класс ModelClass является классом связанной модели.

Таким образом, класс Person имеет связь HasManyRelation (один ко многим) с моделью Animal. Модели связаны через столбцы persons.id и animals.OwneId . В результате мы видим, что у одного человека может быть несколько домашних животных.

Запросы

Начнем с простого запроса SELECT:

Простой SELECT будет выглядеть на Objection.js следующим образом.:

Запрос выше затрагивал все поля в таблице, а так можно реализовать запрос с выбором одного поля:

Из примеров выше видно, насколько запросы в Objection.js похожи на SQL-запросы. Преобразовать одни запросы в другие довольно просто, что нетипично для ORM.

Запросы создания и вставки

Другой способ его выполнения выглядит так:

Запросы удаления

Другой способ его выполнения выглядит так:

Запросы по отношениям

Предположим, мы хотим получить данные обо всех домашних животных пользователя по имени Бен:

Теперь предположим, что вы хотите добавить информацию о пользователе со всеми его животными. Для этого можно использовать запрос с помощью графа:

Доступные плагины

objection-password — плагин, который позволяет автоматически хэшировать пароли для модели Objection.js. Это легкий способ защитить пароли и другие конфиденциальные данные.

objection-graphql — автоматически генерирует GraphQL API для модели Objection.js.

Заключение

В заключение стоит отметить, что если передо мной встанет выбор, какую ORM использовать, я выберу Objection.js. В первую очередь потому, что запросы в ней выполняются проще, чем в sequalize.

В целом Objection.js не похоже на другие ORM. По сути, это просто оболочка поверх конструктора запросов KNEX.js, поэтому лучше всего воспринимать решение как конструктор запросов с дополнительными функциями.

Источник: https://habr.com/ru/company/hexlet/blog/660359/


Интересные статьи

Интересные статьи

Летом 2021 года Microsoft и GitHub представили нейросетевого помощника программиста Copilot  на базе технологий компании Open AI. Авторы проекта научили Copilot премудростям работы с фреймворками...
Prisma — это ORM нового поколения для Node.js и TypeScript. После более чем двух лет разработки мы рады сообщить, что все инструменты Prisma готовы к эксплуатации в production! Содержание Но...
В этой статье мы собираемся создать пайплайн непрерывной интеграции (CI) с Tekton, фреймворком с открытым исходным кодом для создания конвейеров CI / CD в Kubernetes. Мы собираемся подго...
Введение Очень часто, как и в точных науках (физика, химия), так и в прочих областях (экономика, социология, маркетинг и пр.) при работе с разного рода экспериментально полученными зависимостями...
Всем привет! Сегодня делимся с вами познавательным материалом, перевод которого подготовлен специально для студентов курса «ReactJS/React Native-разработчик». Итак, начнем. Все мы видел...