How to connect Node.js with a database?
Node.js applications frequently need to interact with databases to store and retrieve data. This guide covers common methods and popular libraries for connecting Node.js with various database types, including SQL and NoSQL databases.
Common Database Types
Databases generally fall into two main categories: SQL (relational) and NoSQL (non-relational). SQL databases like PostgreSQL, MySQL, and SQLite use structured tables, while NoSQL databases like MongoDB and Redis offer more flexible data models.
Connecting to SQL Databases
For SQL databases, you can either use native drivers provided by the database vendor or community, or leverage Object-Relational Mappers (ORMs) or query builders which provide a more abstract and often more secure way to interact with your database.
Example: PostgreSQL with `pg` (Native Driver)
The pg module is a non-blocking PostgreSQL client for Node.js. It supports connections via promises and callbacks.
npm install pg
const { Client } = require('pg');
async function connectToPostgres() {
const client = new Client({
user: 'your_user',
host: 'localhost',
database: 'your_database',
password: 'your_password',
port: 5432,
});
try {
await client.connect();
console.log('Connected to PostgreSQL database!');
const res = await client.query('SELECT NOW()');
console.log('Current time from DB:', res.rows[0].now);
await client.end();
console.log('PostgreSQL connection closed.');
} catch (err) {
console.error('PostgreSQL connection error', err);
}
}
connectToPostgres();
Example: MySQL with `mysql2` (Native Driver)
mysql2 is a fast MySQL client for Node.js, offering better performance and advanced features compared to the older mysql package. It supports promises and connection pooling.
npm install mysql2
const mysql = require('mysql2/promise');
async function connectToMySQL() {
const connection = await mysql.createConnection({
host: 'localhost',
user: 'your_user',
database: 'your_database',
password: 'your_password',
port: 3306
});
try {
console.log('Connected to MySQL database!');
const [rows, fields] = await connection.execute('SELECT 1 + 1 AS solution');
console.log('The solution is:', rows[0].solution);
await connection.end();
console.log('MySQL connection closed.');
} catch (err) {
console.error('MySQL connection error', err);
}
}
connectToMySQL();
Example: SQLite with `sqlite3`
sqlite3 provides a Node.js interface to the SQLite database. SQLite is a lightweight, file-based database ideal for local development or small applications.
npm install sqlite3
const sqlite3 = require('sqlite3').verbose();
function connectToSQLite() {
const db = new sqlite3.Database('./mydb.sqlite', (err) => {
if (err) {
return console.error(err.message);
}
console.log('Connected to the SQLite database.');
});
db.serialize(() => {
db.run('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
db.run('INSERT INTO users(name) VALUES(?)', ['John Doe'], function(err) {
if (err) {
return console.log(err.message);
}
console.log(`A row has been inserted with rowid ${this.lastID}`);
});
db.each('SELECT id, name FROM users', (err, row) => {
if (err) {
console.error(err.message);
}
console.log(row.id + "\t" + row.name);
});
});
db.close((err) => {
if (err) {
return console.error(err.message);
}
console.log('Closed the SQLite database connection.');
});
}
connectToSQLite();
Connecting to NoSQL Databases
NoSQL databases are designed for specific data models and have flexible schemas. They often use official client drivers or Object-Document Mappers (ODMs) for Node.js.
Example: MongoDB with `mongoose` (ODM)
Mongoose is an elegant MongoDB object modeling tool for Node.js. It helps manage relationships between data, provides schema validation, and is widely used for MongoDB integration.
npm install mongoose
const mongoose = require('mongoose');
async function connectToMongoDB() {
try {
await mongoose.connect('mongodb://localhost:27017/your_database', {
useNewUrlParser: true,
useUnifiedTopology: true
});
console.log('Connected to MongoDB database!');
const UserSchema = new mongoose.Schema({
name: String,
email: String
});
const User = mongoose.model('User', UserSchema);
const newUser = new User({ name: 'Jane Doe', email: 'jane@example.com' });
await newUser.save();
console.log('User saved:', newUser);
const users = await User.find({});
console.log('All users:', users);
await mongoose.connection.close();
console.log('MongoDB connection closed.');
} catch (err) {
console.error('MongoDB connection error', err);
}
}
connectToMongoDB();
Example: Redis with `ioredis`
Redis is an in-memory data structure store, used as a database, cache, and message broker. ioredis is a robust, performance-focused Redis client for Node.js.
npm install ioredis
const Redis = require('ioredis');
async function connectToRedis() {
const redis = new Redis({
port: 6379, // Redis port
host: '127.0.0.1' // Redis host
// password: 'your_redis_password',
// db: 0, // Defaults to 0
});
redis.on('connect', () => {
console.log('Connected to Redis!');
});
redis.on('error', (err) => {
console.error('Redis connection error', err);
});
try {
await redis.set('mykey', 'Hello Redis from Node.js!');
const value = await redis.get('mykey');
console.log('Value from Redis:', value);
await redis.hset('user:1', 'name', 'Alice', 'age', 30);
const user = await redis.hgetall('user:1');
console.log('User from Redis:', user);
await redis.del('mykey', 'user:1');
console.log('Keys deleted.');
redis.quit();
console.log('Redis connection closed.');
} catch (err) {
console.error('Redis operation error', err);
}
}
connectToRedis();
Using ORMs/ODMs for Abstraction
Object-Relational Mappers (ORMs) for SQL databases and Object-Document Mappers (ODMs) for NoSQL databases abstract away raw database queries, allowing developers to interact with databases using object-oriented paradigms. They often provide features like schema definition, data validation, and query building.
- Sequelize: A promise-based Node.js ORM for PostgreSQL, MySQL, MariaDB, SQLite, and SQL Server.
- TypeORM: An ORM that can run in NodeJS, Browser, React Native, Expo, and Electron. Supports MySQL, PostgreSQL, MariaDB, SQLite, Microsoft SQL Server, Oracle, SAP Hana, Aurora Data API.
- Prisma: A next-generation ORM that makes it easy for app developers to build performant apps faster. Supports PostgreSQL, MySQL, SQLite, SQL Server, MongoDB, CockroachDB.
- Mongoose: (MongoDB ODM) Provides a straightforward, schema-based solution to model your application data.
- Knex.js: A SQL query builder for PostgreSQL, MySQL, CockroachDB, MariaDB, SQLite3, Oracle, and Amazon Redshift. Often used as a base for other ORMs like Objection.js.
Best Practices
- Environment Variables: Always store sensitive database credentials (host, user, password, port) in environment variables, not directly in your code.
- Connection Pooling: Use connection pooling for SQL databases to efficiently manage and reuse database connections, reducing overhead and improving performance.
- Error Handling and Retries: Implement robust error handling for database operations and consider retry mechanisms for transient connection issues.
- Input Sanitization/Prepared Statements: Prevent SQL injection attacks by using parameterized queries (prepared statements) or ORMs that handle sanitization automatically.
- Choose Wisely: Select the database and the appropriate driver/ORM based on your project's specific requirements, data structure, scalability needs, and team familiarity.
- Close Connections: Ensure database connections are properly closed when no longer needed, especially for standalone scripts. Web servers usually maintain persistent connections or pools.