Введение в базы данных

Существует 2 основных типа баз данных. Первая называется нереляционной базой данных, а вторая, как вы уже догадались, реляционной базой данных. Было много шума вокруг нереляционных баз данных, которые решат все узкие места реляционных баз данных, но это не так. В отрасли 95% приложений не нуждаются в нереляционных базах данных. Итак, мой вам совет — используйте нереляционную базу данных только тогда, когда вы не знаете структуру данных. Все остальное можно решить с помощью реляционной базы данных.

Оглавление:

PostgreSQL

База данных, которую мы собираемся использовать, называется PostgreSQL и является реляционной базой данных. Язык запросов, используемый PostgreSQL, конечно же, SQL. PostgreSQL датируется 1986 годом и был создан как проект Калифорнийского университета в Беркли. Разработка PostgreSQL все еще активна сегодня, и она используется многими компаниями в отрасли. Она соответствует требованиям ACID, надежна, предсказуема и работает на большинстве операционных систем.

Установить PostgreSQL

Мой любимый способ обработки внешних зависимостей при разработке — через Docker. Docker — это виртуальная среда, которая может имитировать различные виды операционных систем. Docker может запускать контейнеризованные приложения. Это означает, что мы можем запускать контейнерную версию PostgreSQL, не устанавливая ее на свои машины. Он будет установлен через Docker. Docker — это отдельная тема, и она будет рассмотрена в следующем посте. Вывод здесь заключается в том, что его действительно легко освоить, он делает разработку более удобной, и мы можем развертывать приложения предсказуемым образом.

  1. Скачайте Докер.
  2. Запустите образ Docker, содержащий PostgreSQL (в терминале)
docker run --name picoblog-db -e POSTGRES_PASSWORD=mypassword -p 5432:5432 -d postgres

Объяснение команды выше:

docker run запускает указанный образ докера.

--name он дает имя образу, который мы запускаем, чтобы мы могли сослаться на него позже.

-e он передает переменные среды в базовую ОС, на которой работает образ докера.

-d запускает образ в отсоединенном режиме, что означает, что после выполнения команды в терминале он вернется и образ продолжит работать в фоновом режиме.

-p 5432:5432 связывает порт докера 5432 с внешним портом 5432, чтобы мы могли получить доступ к базе данных за пределами контейнера докера (например, с локального хоста). Итак, если вы думаете, что docker — это другой компьютер, у него есть экземпляр postgres, работающий на порту 5432. Однако с другого компьютера мы не можем получить доступ к этому порту, потому что это внутренний порт этой машины. . Используя параметр -p, мы можем указать, какой порт докер должен показывать миру.

Следовательно, это запустит образ докера postgres в автономном режиме. Это даст ему имя picoblog-db, которое можно использовать позже, чтобы убить его или выполнить различные действия с этим изображением. Наконец, он передаст переменную окружения POSTGRES_PASSWORD=mypassword.

3. Убедитесь, что база данных работает.

Вы должны увидеть что-то похожее на это.

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 738782899beb postgres "docker-entrypoint.s..." About a minute ago Up About a minute 5432/tcp picoblog-db

Это означает, что база данных работает на порту 5432.

Использование баз данных в Node.js

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

  1. Необработанные SQL-запросы
  2. ORM, что означает объектно-реляционное сопоставление
  3. Конструкторы запросов

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

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

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

Я выбрал конструктор запросов Knex. Подробнее о Knex можно узнать здесь.

Как установить Кекс

  1. Перейдите в домашний каталог приложения.
  2. Импортируйте библиотеку Knex в наше приложение, как и прежде, мы можем сделать
npm install knex

Таким образом, наш файл package.json теперь будет включать эту зависимость. Далее, поскольку мы хотим использовать Knex с PostgresSQL, мы также должны установить соответствующую зависимость базы данных.

npm install pg

Еще раз, это добавит зависимость в файл package.json.

Подключиться к базе данных PostgreSQL через терминал

Во-первых, прежде чем пытаться подключиться к postgres программно, давайте сначала попробуем подключиться с помощью терминала. Для этого на вашем компьютере должен быть установлен psql. Поскольку я использую компьютер Mac, моим менеджером пакетов является Homebrew. Вы можете установить его, следуя этому руководству. После того, как homebrew будет установлен на вашем компьютере, вы можете установить postgres, набрав в своем терминале

brew install postgres

Это установит postgres на ваш компьютер и даст инструмент cli для подключения к экземплярам postgres. Для подключения введите

psql -h localhost -U postgres

он попросит вас ввести пароль, который мы определили при запуске образа докера, который был mypassword. После того, как вы введете свой пароль, вы можете перечислить базы данных, таблицы и в значительной степени выполнить запросы sql.

Подключиться к PostgreSQL через Postico

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

После подключения вы сможете увидеть что-то похожее на это.

Получение списка баз данных Postgres

Чтобы просмотреть всю доступную базу данных postgres, вы можете сделать это, набрав \list или \l для сокращения.

Как вы можете видеть на изображении выше, я подключился к работающей базе данных и перечислил все доступные базы данных. Это базы данных postgres по умолчанию, и они должны оставаться в неизменном состоянии, потому что, когда мы создаем новую базу данных, postgres фактически копирует одну из этих баз данных шаблонов в качестве отправной точки. Подробнее об этом можно прочитать в официальной документации postgres. Базу данных с именем postgres можно безопасно удалить, но я пока оставлю ее там.

Схема базы данных

Теперь самое время приступить к определению нашей схемы. Пока у нас есть users и posts.

Какую информацию мы хотим отслеживать для пользователя?

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

Какую информацию мы хотим отслеживать для публикации?

Мы должны отслеживать содержание поста, дату его создания, автора каждого поста и т. д. Это первая итерация нашего приложения. Позже мы рассмотрим, как перенести нашу базу данных, чтобы расширить ее, возможно, дополнительными объектами или расширить наши существующие объекты дополнительными полями. Например, мы можем захотеть добавить к сообщениям дополнительное поле, называемое тегами, чтобы мы могли искать и находить релевантные сообщения.

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

Давайте посмотрим, как мы можем создать наши таблицы и смоделировать предыдущие 2 объекта в нашей базе данных, используя Knex и некоторый код javascript.

Как подключиться к postgres из Knex

2. Запустите knex init, чтобы создать knexfile.js с конфигурациями базы данных для разных сред.

Чтобы knex работал в нашей конфигурации, как на данный момент, knexfile.js должен быть таким, как показано ниже.

module.exports = { development: { client: 'pg', connection: { database: 'postgres', user: 'postgres', password: 'mypassword' }, pool: { min: 2, max: 10 }, migrations: { directory: __dirname + '/knex/migrations' } }, production: { client: 'pg', connection: { database: 'postgres', user: 'postgres', password: 'mypassword' }, pool: { min: 2, max: 10 }, migrations: { directory: __dirname + '/knex/migrations' } } };

3. Затем в корневом каталоге нашего проекта создаем папку с именем knex. Внутри создайте файл с именем knex.js, который будет иметь следующее

const environment = process.env.ENVIRONMENT || 'development' const config = require('../knexfile.js')[environment]; module.exports = require('knex')(config);

Это экспортирует конфигурацию knex, поэтому ее можно повторно использовать в приложении.

4. Создайте миграцию knex для создания таблицы пользователей.

knex migrate:make create_users_table --knexpath knex/migrations

Это создаст файл под /knex/migrations. Файл выглядит примерно так. Я преобразовал функции в стрелочные функции.

exports.up = (knex, Promise) => { return knex.schema.createTable('users', (t) => { t.increments('id').unsigned().primary(); t.dateTime('createdAt').notNull(); t.dateTime('updatedAt').nullable(); t.dateTime('deletedAt').nullable(); t.string('name').notNull(); t.string('surname').notNull(); t.string('email').unique().notNull(); t.string('password').notNull(); }); }; exports.down = (knex, Promise) => { return knex.schema.dropTable('users'); };

Это говорит knex создать таблицу пользователей с 8 указанными заполнениями, когда мы запускаем миграцию. С другой стороны, мы также можем выполнить откат, и это удалит таблицу (например, удалит таблицу со всеми ее данными).

5. Наконец, чтобы создать таблицу, которую вы можете сделать

knex migrate:latest

Это запустит каждую миграцию, которая у нас есть. Это может быть больше, чем просто 1 файл. На данный момент, проверяя базу данных Postico, мы видим, что у нас есть 3 новые таблицы. Созданная нами таблица users и еще 2 таблицы для миграции knex.

6. Для отката мы можем сделать

knex migrate:rollback

Это приведет к откату последней примененной нами миграции. Вам не обязательно выполнять этот шаг.

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

Структура проекта должна выглядеть так

microblog/ knex/ migrations/ 20190325211227_create_users_table.js knex.js node_modules/ routes/ index.js login.js views/ partials/ navigation.hbs index.hbs app.js knexfile.js package.json package-lock.json

Таблица сообщений

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

knex migrate:make create_posts_table --knexpath knex/migrations

Это создаст файл под /knex/migrations. Файл выглядит примерно так. Я преобразовал функции в стрелочные функции, как и раньше.

exports.up = (knex, Promise) => { return knex.schema.createTable('posts', (t) => { t.increments('id').unsigned().primary(); t.dateTime('createdAt').notNull(); t.dateTime('updatedAt').nullable(); t.dateTime('deletedAt').nullable(); t.string('title').notNull(); t.string('body').notNull(); t.integer('user_id').unsigned(); t.foreign('user_id').references('id').inTable('users'); }); }; exports.down = (knex, Promise) => { return knex.schema.dropTable('posts'); };

Как мы видели ранее, выполняя

knex migrate:latest

мы можем запустить все миграции, которые еще не были применены. Итак, таблица сообщений будет создана, и глядя на Postico, мы можем увидеть новую таблицу. Глядя на Postico, мы можем наблюдать нечто подобное

Если мы хотим откатиться, мы можем сделать

knex migrate:rollback

Опять же, вам не нужно выполнять этот шаг, так как он удалит таблицы users и posts.

Ограничения внешнего ключа (отношения «один ко многим»)

И последнее, но не менее важное: мы должны добавить foreign key в таблицу posts. Это позволит нам создать отношение типа один ко многим. Другими словами, это означает, что один пользователь может иметь несколько (или много) сообщений. Позже мы сможем запросить нашу базу данных, используя эту информацию. Мы сможем ответить на такие вопросы, как «Дайте мне все сообщения для пользователя по имени Джон». С базой данных SQL вы пытаетесь зафиксировать все отношения, существующие в домене приложения на уровне базы данных.

UML-диаграмма базы данных

Вот как наша база данных выглядит на диаграмме UML. Как видите, между таблицами users и posts существует отношение "один ко многим".

Структура в конце этого проекта выглядит так

microblog/ knex/ migrations/ 20190325211227_create_users_table.js 20190401214024_create_posts_table.js knex.js node_modules/ routes/ index.js login.js views/ partials/ navigation.hbs index.hbs app.js knexfile.js package.json package-lock.json

Поздравляем, вы завершили главу 4. В этой главе мы узнаем о базах данных и о том, как использовать knex для создания миграций. Миграция изменений базы данных является чем-то неизбежным и обязательно произойдет, если вы работаете с реальным приложением. Цель этого руководства — изучить основы использования Postgres и Knex, а также узнать, как работать с реальным приложением и чем-то, что может работать в производственной среде.

Вы можете найти окончательный результат этой главы на Github.

Если вам понравился урок, рассмотрите возможность подписаться на мой блог. Таким образом я узнаю, что моя работа ценна для вас, а также уведомляю вас о будущих уроках. Быть в курсе!

Первоначально опубликовано на https://picocoder.io 1 апреля 2019 г.