Ask me anything
Ithy Logo
Sign in to save

Пошаговое руководство по созданию базы данных и бэкенда для веб-сайта товаров и услуг

Комплексное решение с использованием PostgreSQL и Node.js для эффективного управления

e commerce website development

Ключевые выводы

  • Проектирование базы данных: Четкая структура с основными сущностями и связями обеспечивает надежное хранение данных.
  • Безопасность и масштабируемость: Использование современных технологий и методов защиты гарантирует безопасность и возможность роста приложения.
  • Эффективная реализация бэкенда: Node.js и Express обеспечивают высокую производительность и гибкость при разработке серверной части.

1. Проектирование базы данных

Определение сущностей и их связей

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

Основные таблицы

Таблица Описание
users Хранит информацию о пользователях, включая авторизацию и роли.
categories Содержит категории и подкатегории товаров и услуг.
products Хранит данные о товарах, включая описание, цену и фото.
services Содержит информацию об услугах, описания и примеры проектов.
projects Примеры выполненных проектов с фотографиями и комментариями.
comments Комментарии пользователей к проектам.
orders Информация о заказах пользователей, включая статус и сумму.
order_items Детали заказов, связывающие продукты и услуги с конкретными заказами.

Диаграмма сущностей

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

2. Создание базы данных в PostgreSQL

Определение и создание таблиц

Используя SQL, создаем необходимые таблицы с учетом связей и необходимых ограничений.

Создание таблиц


-- Пользователи
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    role VARCHAR(50) DEFAULT 'user',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Категории
CREATE TABLE categories (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    parent_id INTEGER REFERENCES categories(id) ON DELETE SET NULL,
    type VARCHAR(50) NOT NULL
);

-- Товары
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    category_id INTEGER REFERENCES categories(id) ON DELETE SET NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    price DECIMAL(10, 2) NOT NULL,
    image_url TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Услуги
CREATE TABLE services (
    id SERIAL PRIMARY KEY,
    category_id INTEGER REFERENCES categories(id) ON DELETE SET NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    price DECIMAL(10, 2),
    image_url TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Примеры проектов
CREATE TABLE projects (
    id SERIAL PRIMARY KEY,
    service_id INTEGER REFERENCES services(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    image_url TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Комментарии
CREATE TABLE comments (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
    project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Заказы
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
    total_amount DECIMAL(10, 2) NOT NULL,
    status VARCHAR(50) DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Элементы заказа
CREATE TABLE order_items (
    id SERIAL PRIMARY KEY,
    order_id INTEGER REFERENCES orders(id) ON DELETE CASCADE,
    product_id INTEGER REFERENCES products(id) ON DELETE SET NULL,
    service_id INTEGER REFERENCES services(id) ON DELETE SET NULL,
    quantity INTEGER NOT NULL,
    price DECIMAL(10, 2) NOT NULL
);
  

3. Настройка Node.js и Express

Установка зависимостей и настройка сервера

Для создания бэкенда используем Node.js с фреймворком Express и подключением к PostgreSQL через библиотеку pg. Также применяем bcrypt для хэширования паролей и JSON Web Tokens (JWT) для аутентификации.

Инициализация проекта и установка зависимостей


npm init -y
npm install express pg bcrypt jsonwebtoken dotenv cors helmet express-rate-limit
  

Создание структуры проекта


ecommerce-backend/
├── .env
├── app.js
├── config/
│   └── db.js
├── models/
│   ├── userModel.js
│   ├── productModel.js
│   └── serviceModel.js
├── routes/
│   ├── authRoutes.js
│   ├── productRoutes.js
│   └── serviceRoutes.js
└── controllers/
    ├── authController.js
    ├── productController.js
    └── serviceController.js
  

Настройка соединения с базой данных


const { Pool } = require('pg');
const dotenv = require('dotenv');

dotenv.config();

const pool = new Pool({
    user: process.env.DB_USER,
    host: process.env.DB_HOST,
    database: process.env.DB_NAME,
    password: process.env.DB_PASSWORD,
    port: process.env.DB_PORT,
});

module.exports = pool;
  

Настройка сервера Express


const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const dotenv = require('dotenv');

const authRoutes = require('./routes/authRoutes');
const productRoutes = require('./routes/productRoutes');
const serviceRoutes = require('./routes/serviceRoutes');

dotenv.config();

const app = express();

// Middleware для безопасности
app.use(helmet());
app.use(cors());
app.use(express.json());

// Ограничение запросов
const limiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 минут
    max: 100 // максимум 100 запросов
});
app.use(limiter);

// Маршруты
app.use('/api/auth', authRoutes);
app.use('/api/products', productRoutes);
app.use('/api/services', serviceRoutes);

// Обработка ошибок
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).json({ error: 'Что-то пошло не так!' });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Сервер запущен на порту ${PORT}`);
});
  

4. Реализация аутентификации пользователей

Регистрация и авторизация с использованием JWT

Для обеспечения безопасности доступа к ресурсам веб-сайта реализуем регистрацию и авторизацию пользователей с помощью JWT.

Контроллеры аутентификации


// controllers/authController.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const pool = require('../config/db');

const register = async (req, res) => {
    const { username, email, password } = req.body;
    try {
        const hashedPassword = await bcrypt.hash(password, 10);
        const result = await pool.query(
            'INSERT INTO users (username, email, password_hash) VALUES ($1, $2, $3) RETURNING *',
            [username, email, hashedPassword]
        );
        res.status(201).json(result.rows[0]);
    } catch (error) {
        res.status(500).json({ error: 'Ошибка при регистрации пользователя' });
    }
};

const login = async (req, res) => {
    const { email, password } = req.body;
    try {
        const userResult = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
        if (userResult.rows.length === 0) {
            return res.status(400).json({ error: 'Неверный email или пароль' });
        }
        const user = userResult.rows[0];
        const validPassword = await bcrypt.compare(password, user.password_hash);
        if (!validPassword) {
            return res.status(400).json({ error: 'Неверный email или пароль' });
        }
        const token = jwt.sign(
            { id: user.id, role: user.role },
            process.env.JWT_SECRET,
            { expiresIn: '1h' }
        );
        res.json({ token });
    } catch (error) {
        res.status(500).json({ error: 'Ошибка при аутентификации пользователя' });
    }
};

module.exports = { register, login };
  

Маршруты аутентификации


// routes/authRoutes.js
const express = require('express');
const { register, login } = require('../controllers/authController');
const router = express.Router();

router.post('/register', register);
router.post('/login', login);

module.exports = router;
  

Мидлвар для проверки JWT


// middleware/authMiddleware.js
const jwt = require('jsonwebtoken');

const authenticateToken = (req, res, next) => {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];
    if (token == null) return res.status(401).json({ error: 'Токен не предоставлен' });

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
        if (err) return res.status(403).json({ error: 'Неверный токен' });
        req.user = user;
        next();
    });
};

module.exports = authenticateToken;
  

5. Реализация функционала заказов

Создание и управление заказами товаров и услуг

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

Контроллеры заказов


// controllers/orderController.js
const pool = require('../config/db');

const createOrder = async (req, res) => {
    const { items } = req.body;
    const userId = req.user.id;
    try {
        await pool.query('BEGIN');
        const totalAmount = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
        const orderResult = await pool.query(
            'INSERT INTO orders (user_id, total_amount) VALUES ($1, $2) RETURNING *',
            [userId, totalAmount]
        );
        const orderId = orderResult.rows[0].id;

        for (const item of items) {
            await pool.query(
                'INSERT INTO order_items (order_id, product_id, service_id, quantity, price) VALUES ($1, $2, $3, $4, $5)',
                [orderId, item.product_id || null, item.service_id || null, item.quantity, item.price]
            );
        }

        await pool.query('COMMIT');
        res.status(201).json(orderResult.rows[0]);
    } catch (error) {
        await pool.query('ROLLBACK');
        res.status(500).json({ error: 'Ошибка при создании заказа' });
    }
};

const getOrders = async (req, res) => {
    const userId = req.user.id;
    try {
        const orders = await pool.query('SELECT * FROM orders WHERE user_id = $1', [userId]);
        res.json(orders.rows);
    } catch (error) {
        res.status(500).json({ error: 'Ошибка при получении заказов' });
    }
};

module.exports = { createOrder, getOrders };
  

Маршруты заказов


// routes/orderRoutes.js
const express = require('express');
const { createOrder, getOrders } = require('../controllers/orderController');
const authenticateToken = require('../middleware/authMiddleware');
const router = express.Router();

router.post('/', authenticateToken, createOrder);
router.get('/', authenticateToken, getOrders);

module.exports = router;
  

6. Обеспечение безопасности и масштабируемости

Применение лучших практик для защиты данных и увеличения производительности

Для обеспечения безопасности и масштабируемости необходимо внедрить несколько ключевых практик в процессе разработки и эксплуатации приложения.

Безопасность

  • Использование HTTPS для защиты данных при передаче.
  • Хэширование паролей с помощью bcrypt для защиты учетных записей.
  • Валидация входных данных для предотвращения SQL-инъекций и XSS-атак.
  • Ограничение доступа к API с помощью ролей пользователей.
  • Применение Helmet для добавления HTTP-заголовков безопасности.
  • Использование CORS для контроля доступа к ресурсам API.
  • Ограничение количества запросов с помощью express-rate-limit для предотвращения DDoS-атак.

Масштабируемость

  • Использование пулов соединений PostgreSQL для эффективного управления подключениями.
  • Внедрение кеширования с помощью Redis для ускорения доступа к часто запрашиваемым данным.
  • Оптимизация SQL-запросов и создание индексов на часто используемых полях.
  • Горизонтальное масштабирование приложения с использованием контейнеров Docker и оркестраторов, таких как Kubernetes.
  • Использование балансировщиков нагрузки для распределения трафика между серверами.

7. Тестирование и развертывание

Обеспечение стабильности и доступности приложения

После разработки необходимо тщательно протестировать приложение и подготовить его к развертыванию на продакшн-сервере.

Тестирование

  • Использование инструментов, таких как Postman, для тестирования API эндпоинтов.
  • Написание модульных и интеграционных тестов с помощью Jest или Mocha.
  • Проведение нагрузочного тестирования для оценки производительности под высокой нагрузкой.

Развертывание

  • Использование Docker для контейнеризации приложения, что обеспечивает консистентность окружения.
  • Развертывание на облачных платформах, таких как AWS, Heroku или DigitalOcean.
  • Настройка CI/CD процессов для автоматического тестирования и развертывания при изменениях кода.
  • Мониторинг приложения с помощью инструментов, таких как Prometheus и Grafana, для отслеживания производительности и обнаружения проблем.

Заключение

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


Ресурсы и ссылки


Last updated January 20, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI