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 и успешно запустить его, нам потребуется следующее:
- Config - конфигурация, необходимая для запуска Sequelize
- Миграции - файлы, содержащие все изменения, которые мы вносим в наши таблицы.
- Модели - структура наших таблиц и их свойства
- Сеялки - для инициализации наших таблиц данными по умолчанию
Чтобы иметь необходимые файлы на месте, мы можем либо создать эти папки вручную, либо лучшая альтернатива - просто использовать для этого 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