The E-Commerce API uses MySQL as its relational database, leveraging connection pooling for efficient resource management and raw SQL queries for data operations.
The database connection is configured using the mysql2/promise library with connection pooling:
config/db.mjs
import mysql from 'mysql2/promise';import dotenv from 'dotenv';dotenv.config();const db = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME,});export default db;
Connection pooling automatically manages multiple database connections, reusing them across requests for better performance.
The mysql2 connection pool provides several benefits:
Why use connection pooling?
Performance: Reuses existing connections instead of creating new ones for each request, reducing overhead.Resource management: Limits the number of concurrent connections to prevent overwhelming the database server.Automatic cleanup: Handles connection lifecycle, including error recovery and connection release.Concurrency: Multiple requests can share the pool, with connections automatically allocated and freed.
CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, profile_photo VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE carts ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, product_id INT NOT NULL, variant VARCHAR(255), quantity INT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE);
Example query from source
cartController.mjs
// Check existing cart item with variantconst [cart] = await db.execute( "SELECT * FROM carts WHERE user_id = ? AND product_id = ? AND variant = ?", [userId, productId, variant]);if (cart.length > 0) { // Update quantity if exists await db.execute( "UPDATE carts SET quantity = ? WHERE id = ?", [quantity, cart[0].id] );} else { // Insert new cart item await db.execute( "INSERT INTO carts (user_id, product_id, variant, quantity) VALUES (?, ?, ?, ?)", [userId, productId, variant, quantity] );}
CREATE TABLE reviews ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, product_id INT NOT NULL, rating INT NOT NULL, comment TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE);
CREATE TABLE addresses ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, street VARCHAR(255) NOT NULL, city VARCHAR(100) NOT NULL, state VARCHAR(100) NOT NULL, postal_code VARCHAR(20) NOT NULL, country VARCHAR(100) NOT NULL, is_default BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE);
const [product] = await db.execute( `SELECT p.*, c.name AS category_name, c.slug AS category_slug FROM products p LEFT JOIN categories c ON p.category_id = c.id WHERE p.slug = ?`, [slug]);