Подключение к базе данных: обзор
Где по-настоящему живут данные приложения и как Node с ними общается.
В реальном приложении данные хранят в базе данных, а не в массиве: так они переживают перезапуск сервера и доступны нескольким процессам сразу.
Почему массива недостаточно
В прошлых уроках задачи лежали в массиве в памяти. Это годится для учёбы, но в продакшене данные исчезнут при перезапуске и не разделятся между серверами. База данных решает обе проблемы: данные сохраняются на диск и доступны всем.
Два больших семейства баз
| SQL (реляционные) | NoSQL |
| PostgreSQL, MySQL, SQLite | MongoDB, Redis |
| таблицы, строки, связи | документы, ключ-значение |
| строгая схема | гибкая схема |
| язык SQL | API/запросы драйвера |
Драйвер или ORM
Из Node к базе обращаются двумя способами:
- Драйвер — низкоуровневый пакет, вы пишете запросы сами (например,
pgдля PostgreSQL,mongodbдля Mongo). - ORM/ODM — библиотека, которая отображает строки/документы на объекты JavaScript и сама генерирует запросы (Prisma, Sequelize, Mongoose).
Так выглядит запрос через драйвер pg (код использует npm-пакет, поэтому не запускается в браузере):
const { Pool } = require("pg");
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
async function getTasks() {
const result = await pool.query("SELECT * FROM tasks");
return result.rows;
}
Обратите внимание: pool.query возвращает промис — обращение к БД всегда асинхронно (это сетевой ввод-вывод, как раз то, для чего Node и неблокирующий).
Пул соединений
Открывать новое соединение с БД на каждый запрос дорого. Поэтому используют пул — заранее открытый набор соединений, которые переиспользуются. Pool в примере выше как раз про это.
Защита от SQL-инъекций
Никогда не склеивайте SQL-запрос со строкой от пользователя — это открывает дыру SQL-инъекции. Используйте параметры-плейсхолдеры, драйвер сам их безопасно подставит:
// ОПАСНО — не делайте так:
// pool.query("SELECT * FROM users WHERE id = " + req.params.id)
// БЕЗОПАСНО — параметр через плейсхолдер:
pool.query("SELECT * FROM users WHERE id = $1", [req.params.id]);
Результат запроса — обычные объекты
Что бы ни вернула БД, в Node это станет обычными JS-объектами, с которыми работаешь как всегда:
// имитируем result.rows из БД
const rows = [
{ id: 1, title: "Купить хлеб", done: false },
{ id: 2, title: "Позвонить врачу", done: true }
];
const pending = rows.filter(r => !r.done);
console.log("Невыполненных задач:", pending.length);
console.log("Заголовки:", rows.map(r => r.title));
Вывод:
Невыполненных задач: 1 Заголовки: [ 'Купить хлеб', 'Позвонить врачу' ]
Итог
- Реальные данные хранят в БД: они переживают перезапуск и общие для процессов.
- Базы делятся на SQL (таблицы) и NoSQL (документы/ключ-значение).
- Из Node работают через драйвер (
pg,mongodb) или ORM (Prisma, Sequelize). - Запросы к БД асинхронны; используйте пул соединений и параметры от инъекций.