Sequelize, возможно, одна из лучших ORM-библиотек NodeJS, доступных разработчикам. Однако, как и в случае с любым другим инструментом или фреймворком, есть некоторые проблемы, с которыми мы сталкиваемся, когда впервые приступаем к работе с Sequelize. Их документация довольно исчерпывающая со списком всех функций, которые они предоставляют, в этой статье мы увидим очень последовательный способ создания проекта с помощью Sequelize и то, как мы можем применить изменения к нашим моделям на основе нашего развивающегося приложения ( с).

Настройка проекта

В большинстве приложений вы будете создавать (или использовать уже существующее) приложение API, которое построено с использованием инфраструктуры на основе NodeJS, такой как ExpressJS или NextJS.

В нашем примере мы собираемся сосредоточиться исключительно на Sequelize и не будем зависеть от фреймворка (-ов) NodeJS. Для этого давайте сначала создадим пустой проект NodeJS. Для этого создайте папку проекта sequelize-setup, а затем выполните следующую команду в корне папки. Ответьте на вопросы по описанию ваших проектов.

npm init

После того, как вы ответите на все вопросы, вы увидите базовый файл package.json, созданный в корне

Теперь, чтобы иметь возможность использовать Sequelize в нашем проекте, нам нужно будет установить Sequelize и соответствующий клиент базы данных для выбранной нами базы данных. Нам нужен клиент базы данных, потому что Sequelize - это просто библиотека, которая реализует технику ORM для обработки и запроса данных объектно-ориентированным способом и не содержит дополнительных уровней для взаимодействия с базой данных ниже.

npm i -S sequelize pg

В этом примере мы будем использовать Postgres, инструкции по установке которого доступны здесь, однако самый простой способ установить службу - использовать Homebrew. Итак, установите Homebrew, а затем выполните следующие команды, чтобы настроить Postgres.

role, который мы только что установили в базе данных Postgres, - это имя пользователя и пароль, которые можно использовать для подключения к любой базе данных в будущем с привилегиями суперпользователя.

Мы также будем использовать Postico для предоставления графического интерфейса для базы данных, поэтому загрузите его здесь.

Инициализировать Sequelize

Чтобы иметь возможность настроить проект на основе Sequelize и успешно запустить его, нам потребуется следующее:

  1. Config - конфигурация, необходимая для запуска Sequelize
  2. Миграции - файлы, содержащие все изменения, которые мы вносим в наши таблицы.
  3. Модели - структура наших таблиц и их свойства
  4. Сеялки - для инициализации наших таблиц данными по умолчанию

Чтобы иметь необходимые файлы на месте, мы можем либо создать эти папки вручную, либо лучшая альтернатива - просто использовать для этого Sequelize CLI.

Чтобы установить cli, выполните следующую команду:

npm install --save sequelize-cli

Теперь мы можем использовать cli, который можно найти по адресу node_modules/.bin/sequelize. Для простоты я опущу префикс node_modules/.bin/ и буду использовать только ключевое слово sequelize, продвигаясь вперед со всеми командами.

Чтобы инициализировать проект с помощью интерфейса командной строки, выполните следующую команду в Терминале в корневом каталоге вашего проекта:

sequelize init

и регистрирует следующее:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
Created “config/config.json”
Successfully created models folder at “/sequelize-setup/models”.
Successfully created migrations folder at “/sequelize-setup/migrations”.
Successfully created seeders folder at “/sequelize-setup/seeders”.

который по сути является нашей конфигурацией + пустая папка для хранения моделей, миграций и сидеров.

Конфиг

Папка config, как и ожидалось, содержит файл с именем config.json, в котором создается объект по умолчанию, поскольку мы беспокоимся только о потоке development, удалите записи test и production из объекта config.json, что оставляет нам следующее:

Как видно из вышеизложенного, мы указали dialect как postgres, а имя пользователя и пароль те же, что были настроены при настройке проекта. Поскольку мы запускаем базу данных локально, host IP - это localhost (127.0.0.1).

Этот config теперь можно использовать для выполнения любых и всех последующих взаимодействий с postgres.

Создание базы данных

Одним из вариантов использования конфигурации является создание необходимой базы данных. Теперь, когда у нас запущена и запущена служба postgres, нам нужно сначала создать базу данных, которая впоследствии может содержать наши таблицы. Эта база данных представлена ​​по ключевому слову database в нашей конфигурации. Чтобы создать базу данных с помощью Sequelize, мы можем просто запустить следующую команду:

sequelize db:create

и это регистрирует следующее:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
Loaded configuration file “config/config.json”.
Using environment “development”.
Database database_development created.

Теперь, чтобы проверить создание, мы будем использовать Postico, который мы скачали ранее. Откройте Postico и щелкните New Favorite, который открывает панель для настройки подключения к базе данных, введите имя базы данных, которую мы только что создали, а также имя пользователя и пароль, необходимые для подключения к этой базе данных.

Нажмите кнопку connect, и вы попадете в представление таблиц этой базы данных, которое на данный момент должно быть пустым.

Модели

Теперь мы готовы создать нашу первую модель, то есть объект, который мы будем сопоставить с таблицей. Создание моделей снова является очень простой задачей, если вы используете интерфейс командной строки Sequelize. Мы будем создавать очень простой и универсальный объект, такой как User, со свойствами firstName и lastName. Чтобы сгенерировать User, просто выполните следующую команду:

sequelize model:generate --name User --attributes firstName:string,lastName:string

И вы видите следующий результат:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
New model was created at /sequelize-setup/models/user.js .
New migration was created at /sequelize-setup/migrations/20180719190326-User.js .

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

Модель пользователя, созданная в папке моделей, содержит определение нашего User со свойствами, которые мы определили, и содержит заполнитель с именем associate, в котором мы можем определять любые будущие ассоциации.

И миграция, созданная в папке миграции:

Вы можете видеть, что этот файл содержит несколько дополнительных полей, чем мы ожидали, это связано с тем, что при первом создании модели соответствующая миграция заключается в создании модели в виде таблицы. Поэтому, когда мы создали модель для User, Sequelize автоматически рекомендует создать таблицу Users с запрошенными свойствами (firstName и lastName) и дополнительными свойствами, такими как id, createdAt и updatedAt.

Интересно отметить, что миграция состоит из двух частей: up и down. При ближайшем рассмотрении мы узнаем, что up возвращает обещание, которое мы хотим выполнить, когда миграция применяется, а down содержит миграцию, которую мы хотим выполнить, когда она отменяется. Таким образом, мы определяем противоположности в функциях up и down.

Также есть причина, по которой имя файла миграции содержит в начале отметку времени. С помощью Sequelize CLI мы можем сгенерировать множество файлов миграции и применить или отменить их по своему усмотрению. Подробнее об этом позже.

Применение миграции

У нас есть модель User и начальная миграция для нее. Чтобы запустить эту миграцию и создать таблицу, просто выполните следующую команду:

sequelize db:migrate

который регистрирует следующее:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
Loaded configuration file “config/config.json”.
Using environment “development”.
== 20180719190326-create-user: migrating =======
== 20180719190326-create-user: migrated (0.054s)

переключитесь на Postico, чтобы проверить изменения:

Мы видим, что на данный момент он содержит две вещи: таблицу Users, как и ожидалось, и таблицу SequelizeMeta, которая содержит список всех миграций, которые были применены к этой базе данных.

Сеялки

Наша БД настроена, наша модель пользователя и таблица настроены, следующий логический шаг - добавить некоторые данные в эту таблицу, так что давайте сделаем это. Мы снова будем использовать Sequelize CLI для создания необходимых сидеров:

sequelize seed:generate --name create-users

Мы просто запускаем команду для создания сеялки, которая регистрирует следующее:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
seeders folder at “.../sequelize-setup/seeders” already exists.
New seed was created at .../sequelize-setup/seeders/20180719192307-create-users.js .

Файл в исходном формате не содержит многого, за исключением того, что он несет ту же структуру файла миграции, то есть с функциями up и down:

Но, в отличие от первоначальной миграции, сидер не содержит фактических функций, которыми мы хотим, чтобы он обладал, вместо этого он содержит смутный пример того, что мы могли бы сделать, в данном случае это bulkInsert и bulkDelete.

Беговая сеялка

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

А чтобы запустить сидер, мы снова можем использовать интерфейс командной строки Sequelize. С сидерами мы получаем более детальный контроль и запускаем конкретный файл сидера, если хотим, или мы можем запустить их все, если необходимо. В нашем текущем сценарии мы собираемся запустить все.

Небольшая ошибка, которую нам нужно иметь в виду, заключается в том, что сидер будет работать со структурой, указанной в миграции, а не в модели, то есть не исключать какие-либо поля, которые вы хотите отображать в таблицах базы данных. Если вы пропустили поле, для которого установлено ограничение NOT NULL, вы получите ошибку.

Имея в виду вышеизложенное, наш сидер для таблицы Users можно создать следующим образом:

И мы можем запустить это с помощью следующей команды:

sequelize db:seed:all

Что выводит сообщение об успешном завершении:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
Loaded configuration file “config/config.json”.
Using environment “development”.
== 20180719192307-create-users: migrating =======
== 20180719192307-create-users: migrated (0.009s)

Мы можем проверить то же самое с помощью Postico в таблице Users:

Изменения и модификации

Часто, особенно на ранних этапах разработки приложения, структура сущностей не фиксируется, и существует несколько сценариев, в которых нам необходимо внести изменения. Например, в этом случае у нас есть только поля firstName и lastName в таблице Users. Давайте изменим это.

Мы добавим новые столбцы с именами age и email. Для этого сначала давайте создадим новый файл миграции с помощью интерфейса командной строки Sequelize:

sequelize migration:generate --name user-updates

Это регистрирует вновь созданный путь к файлу:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
migrations folder at “.../sequelize-setup/migrations” already exists.
New migration was created at .../sequelize-setup/migrations/20180719202036-user-updates.js .

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

Мы просто добавляем / удаляем столбцы и возвращаем их как обещание из наших миграций (обратите внимание на цепочку обещаний). Когда мы запускаем эту миграцию:

sequelize db:migrate

Видим ожидаемый результат:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
Loaded configuration file “config/config.json”.
Using environment “development”.
== 20180719204635-user-updates: migrating =======
== 20180719204635-user-updates: migrated (0.018s)

и мы можем проверить это также в Postico:

Хотя мы указали некоторые правила (проверки), они на самом деле не отображаются в базе данных (очевидно), потому что sequelize применяет эти правила, пока мы пытаемся получить доступ к модели для чтения или обновления. Мы рассмотрим это в отдельной статье.

Обновление модели

Хотя мы создали миграцию и запустили ее, если мы обновим начальное значение и запустим его, мы увидим данные, как и ожидалось. Давайте создадим новый файл сидера с помощью CLI:

sequelize seed:generate --name add-email-age

Что регистрирует вывод следующим образом, обратите внимание на имя файла здесь:

Sequelize CLI [Node: 8.10.0, CLI: 4.0.0, ORM: 4.38.0]
seeders folder at “.../sequelize-setup/seeders” already exists.
New seed was created at .../sequelize-setup/seeders/20180719210102-add-email-age.js .

Давайте добавим в этот сидер новые поля, которые будут очень похожи на существующий исходный файл с небольшими обновлениями:

Теперь, чтобы запустить это, мы выберем этот файл и запустим его, поскольку мы уже добавили данные из предыдущего файла сидера:

sequelize db:seed --seed 20180719210102-add-email-age

Это позволяет нам запускать только один файл, а результат можно увидеть в Postico:

Теперь, когда у нас есть ожидаемые данные, давайте добавим небольшой скрипт, чтобы попытаться запросить данные. В корне проекта создайте файл с именем index.js и добавьте следующую логику для запроса пользователей в зависимости от их возраста:

Мы можем получить пользователей сейчас, и когда мы регистрируем это, мы видим, что зарегистрированный пользователь не имеет поля email и age.

Kashyap-MBP:sequelize-setup kashyap$ node index.js
Executing (default): SELECT “id”, “firstName”, “lastName”, “createdAt”, “updatedAt” FROM “Users” AS “User” WHERE “User”.”age” >= 20;
{ id: 2,
firstName: ‘Jane’,
lastName: ‘Doe’,
createdAt: 2018–07–19T21:08:51.998Z,
updatedAt: 2018–07–19T21:08:51.998Z }

Это связано с тем, что мы не обновили модель для синхронизации с нашим файлом миграции, который использовался для обновления столбцов таблицы Users. Давайте сначала обновим модель с теми же полями:

Когда мы повторно запускаем файл index.js, который мы запускали ранее для запроса таблицы Users:

Kashyap-MBP:sequelize-setup kashyap$ node index.js
Executing (default): SELECT “id”, “firstName”, “lastName”, “email”, “age”, “createdAt”, “updatedAt” FROM “Users” AS “User” WHERE “User”.”age” >= 20;
{ id: 2,
firstName: ‘Jane’,
lastName: ‘Doe’,
email: ‘[email protected]’,
age: 20,
createdAt: 2018–07–19T21:08:51.998Z,
updatedAt: 2018–07–19T21:08:51.998Z }

Теперь мы видим, что он печатает всю структуру пользовательского объекта, как и ожидалось.

Заключение

Sequelize имеет несколько очень мощных функций, которые при правильном использовании могут значительно упростить процесс разработки. В этой статье мы рассмотрели несколько довольно простых способов упростить процесс разработки. Есть более сложные миграции, которые можно применить к Sequelize, о которых я расскажу в другой статье.

Полную кодовую базу можно найти здесь.

Пожалуйста, оставляйте вопросы и комментарии в разделе комментариев ниже.

Если вам понравился этот блог, не забудьте дать ему несколько хлопков или подписаться на меня в LinkedIn