node-mysql-query-utils
A MySQL helper to provide ways to connect to the database, build SQL queries, and perform common database operations for Node.js.
Table of contents
Introduction
node-mysql-query-utils
is a MySQL query builder and helper for Node.js. It provides a simple and easy way to build and execute MySQL queries.
Installation
npm install node-mysql-query-utils
or
yarn add node-mysql-query-utils
Overview
This package provides three classes to help you manage and interact with your MySQL database:
- DatabaseManagement
- SQLBuilder
- TableModel
Quick Start
Here’s a quick overview of how to make use of this library:
import {
DatabaseManagement,
TableModel,
SQLBuilder,
sqlHelper,
} from "node-mysql-query-utils";
DatabaseManagement.connectMultipleDatabases([
{
identifierName: "mainDB",
config: {
host: "localhost",
user: "root",
password: "password",
database: "test_db",
},
options: {
verbose: true,
},
},
]);
DatabaseManagement.connectSingleDatabase(
"mainDB",
{
host: "localhost",
user: "root",
password: "password",
database: "test_db",
},
{
verbose: true,
}
);
const mainDB = DatabaseManagement.getInstance("mainDB");
const columns = sqlHelper.createColumns([
"user_id",
"ctime",
"utime",
"email",
"mobile",
"password",
"is_active",
"is_deleted",
]);
export const userAccountModel = mainDB.createTableModel({
tableName: "user_account",
primaryKey: "user_id",
columns,
centralFields: {
ctimeField: "ctime",
utimeField: "utime",
isActiveField: "is_active",
isDeletedField: "is_deleted",
statusField: "status",
},
});
DatabaseManagement
The DatabaseManagement
class is a singleton class that helps manage database connections. It supports connecting to single or multiple databases and provides a way to retrieve instances of the connections.
Single database connection
import { DatabaseManagement } from "node-mysql-query-utils";
import { ConnectionOptions } from "mysql2/promise";
const config: ConnectionOptions = {
host: "localhost",
user: "root",
password: "password",
database: "test_db",
};
DatabaseManagement.connectSingleDatabase("mainDB", config);
const dbInstance = DatabaseManagement.getInstance("mainDB");
Multiple database connections
import { DatabaseManagement } from "node-mysql-query-utils";
import { type DatabaseConnectionConfig } from "node-mysql-query-utils/dist/dto/types";
const configs: DatabaseConnectionConfig[] = [
{
identifierName: "mainDB",
config: {
host: "localhost",
user: "root",
password: "password",
database: "main_db",
},
},
{
identifierName: "analyticsDB",
config: {
host: "localhost",
user: "root",
password: "password",
database: "analytics_db",
},
},
];
DatabaseManagement.connectMultipleDatabases(configs);
const mainDBInstance = DatabaseManagement.getInstance("mainDB");
const analyticsDBInstance = DatabaseManagement.getInstance("analyticsDB");
SQLBuilder Class
The SQLBuilder
class provides a way to build SQL queries for various operations such as SELECT, INSERT, UPDATE, DELETE, etc.
To generate the final SQL query and its parameters, you must call the .buildQuery()
method at the end of your query-building process.
If the SQLBuilder
constructor is provided with a queryFn
, you can use the .executeQuery()
method to execute the query directly.
Example
import { SQLBuilder, sqlHelper } from "node-mysql-query-utils";
const tableName = "user_account";
const columns = sqlHelper.createColumns([
"user_id",
"ctime",
"utime",
"email",
"mobile",
"password",
"is_active",
"is_deleted",
]);
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const sqlBuilder = new SQLBuilder();
const sqlBuilder = new SQLBuilder(db.query.bind(db));
const sqlBuilder = new SQLBuilder<(typeof columns)[number], any>(
db.query.bind(db)
);
const { sql, params } = sqlBuilder.select().from(tableName).buildQuery();
const [sql, params] = sqlBuilder.select().from(tableName).buildQuery();
const [sql, params] = sqlBuilder
.select()
.from(tableName)
.buildQuery({ format: true });
const result = await db.query(sql, params);
const result = await sqlBuilder.select().from(tableName).executeQuery();
.select() Method
const [sql, params] = sqlBuilder.select().from(tableName).buildQuery();
const [sql, params] = sqlBuilder.select("*").from(tableName).buildQuery();
const [sql, params] = sqlBuilder
.select(["user_id", "email"])
.from(tableName)
.buildQuery();
const [sql, params] = sqlBuilder
.select([{ user_id: "id", mobile: "user_mobile" }, { email: "user_email" }])
.from(tableName)
.buildQuery();
const [sql, params] = sqlBuilder.select("user_id").from(tableName).buildQuery();
.from() Method
const [sql, params] = sqlBuilder.select().from("user_account").buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account", "u")
.buildQuery();
const [sql, params] = sqlBuilder.select().from("user_account u").buildQuery();
.join() Method
const [sql, params] = sqlBuilder
.select()
.from("user_account", "u")
.join(
"INNER",
"user_profile_pic",
"up",
"u.user_profile_pic_id = up.user_profile_pic_id"
)
.buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account", "u")
.join(
"LEFT",
"user_profile_pic",
"up",
"u.user_profile_pic_id = up.user_profile_pic_id"
)
.buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account", "u")
.join(
"RIGHT",
"user_profile_pic",
"up",
"u.user_profile_pic_id = up.user_profile_pic_id"
)
.buildQuery();
Only provide third argument if no alias is needed
const [sql, params] = sqlBuilder
.select()
.from("user_account", "u")
.join(
"INNER",
"user_profile_pic",
"u.user_profile_pic_id = user_profile_pic.user_profile_pic_id"
)
.buildQuery();
.where() Method
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.where({
email: "123@gmail.com",
email: { "=": "123@gmail.com" },
email: { "!=": "123@gmail.com" },
user_id: { ">": 123 },
user_id: { "<": 123 },
user_id: { ">=": 123 },
user_id: { "<=": 123 },
is_active: { BETWEEN: [0, 1] },
is_active: { NOT_BETWEEN: [0, 1] },
status: { IN: [1, 2, 3, 4] },
status: { NOT_IN: [1, 2, 3, 4] },
nickname: { IS_NOT_NULL: true },
nickname: { IS_NULL: true },
nickname: { LIKE: { contains: 'name' } },
nickname: { NOT_LIKE: { startsWith: 'name' } },
nickname: { LIKE: { endsWith: 'name' } },
nickname: { LIKE: '%_123' }
nickname: { REGEXP: '^[a-zA-Z0-9]*$' }
"u.user_id": { "!=": 1 },
})
.buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.where({
email: "123@gmail.com",
is_active: 1,
})
.buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.where({
AND: [{ email: { LIKE: "%@gmail.com" } }, { username: "jane" }],
});
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.where({
OR: [{ email: { LIKE: "%@gmail.com" } }, { username: "jane" }],
});
Supported Operators:
=
!=
>
<
>=
<=
LIKE
,NOT_LIKE
REGEXP
,IN
,NOT_IN
BETWEEN
NOT_BETWEEN
IS_NULL
IS_NOT_NULL
.orderBy() Method
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.orderBy([{ field: "email", direction: "ASC" }])
.buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.orderBy([
{ field: "email", direction: "ASC" },
{ field: "user_id", direction: "DESC" },
])
.buildQuery();
.limit() and .offset() Methods
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.limit(10)
.buildQuery();
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.limit(10)
.offset(5)
.buildQuery();
.insert() Method
const [sql, params] = sqlBuilder
.insert(
"user_account",
{ email: "123@gmail.com" },
{
enableTimestamps = false,
ctimeField = "ctime",
utimeField = "utime",
ctimeValue = Math.floor(Date.now() / 1000),
utimeValue = Math.floor(Date.now() / 1000),
insertIgnore = false,
}
)
.buildQuery();
Insert Options
The insert
method accepts options parameter with the following properties:
Property | Type | Description |
---|
enableTimestamps | boolean | (Optional) If true, will add ctime and utime to the insert object. Default is false. |
ctimeField | string | (Optional) The field name for the create timestamp. Default is ctime . |
utimeField | string | (Optional) The field name for the update timestamp. Default is utime . |
ctimeValue | any | (Optional) The value for the create timestamp. Default is the current Unix timestamp. |
utimeValue | any | (Optional) The value for the update timestamp. Default is the current Unix timestamp. |
insertIgnore | boolean | (Optional) If true, will add IGNORE to the insert query. Default is false. |
.update() Method
const [sql, params] = sqlBuilder
.update(
"user_account",
{ email: "123@gmail.com" },
{
enableTimestamps = false,
utimeField = "utime",
utimeValue = Math.floor(Date.now() / 1000),
}
)
.where({ user_id: 1 })
.buildQuery();
const [sql, params] = sqlBuilder
.update("user_account")
.set({ email: "123@gmail.com" })
.where({ user_id: 1 })
.buildQuery();
const [sql, params] = sqlBuilder
.update("user_account")
.set({ balance: { increment: 100 } })
.where({ user_id: 1 })
.buildQuery();
Update Options
The update
method accepts options parameter with the following properties:
Property | Type | Description |
---|
enableTimestamps | boolean | (Optional) If true, will add utime to the update object. Default is false. |
primaryKey | string | (Optional) The primary key field name. For removing primaryKey in update object |
utimeField | string | (Optional) The field name for the update timestamp. Default is utime . |
utimeValue | any | (Optional) The value for the update timestamp. Default is the current Unix timestamp. |
.delete() Method
const [sql, params] = sqlBuilder.deleteFrom("user_account").buildQuery();
const [sql, params] = sqlBuilder
.deleteFrom("user_account")
.where({ user_id: 1 })
.buildQuery();
const [sql, params] = sqlBuilder
.deleteFrom("user_account")
.where({ user_id: { ">": 1 } })
.limit(1)
.buildQuery();
.buildQuery() Method
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const [sql, params] = sqlBuilder
.select()
.from("user_account")
.buildQuery({ format: true });
.executeQuery() Method
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const result = await sqlBuilder.select().from("user_account").executeQuery();
Without calling .buildQuery() or .executeQuery()
const sqlBuilder = new SQLBuilder<(typeof columns)[number]>();
const result = sqlBuilder.select().from("user_account");
const [sql, params] = result.buildQuery();
const result = await result.executeQuery();
TableModel Class
The TableModel
class is a wrapper around the SQLBuilder
class that provides a way to build and execute common database operations like SELECT, INSERT, UPDATE, DELETE, etc.
To generate the final SQL query and its parameters, you must call the .buildQuery()
method at the end of your query-building process. If you have provided a query function, you can use the .executeQuery()
method to execute the query directly.
There are two ways to define and use the TableModel
class:
1. Using DatabaseManagement to Connect to the Database
Connect database by DatabaseManagement
class can refer to the Quick Start example. This method involves connecting to multiple databases using the DatabaseManagement
class and then retrieving instances to create table models.
2. Using the TableModel Class Directly
Alternatively, you can define the table model by using the TableModel
class directly. This method is useful if you prefer to use your own query function or if you don't connect to the database using the DatabaseManagement
class from this package.
const userModel = new TableModel({
tableName: "users",
primaryKey: "user_id",
columns: sqlHelper.createColumns(["user_id", "name", "email", "phone"]),
queryFn: db.query.bind(db),
});
Methods
The TableModel
class provides the following methods to perform database operations:
| Method | Description |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
| createSelect
| Creates a SELECT query. Returns a function that returns an instance of the SQLBuilder
class. You can chain the SQLBuilder
methods to build your desired query. |
| createInsert
| Creates an INSERT query. Returns a function that returns an instance of the SQLBuilder
class. You can chain the SQLBuilder
methods to build your desired query. |
| createUpdate
| Creates an UPDATE query. Returns a function that returns an instance of the SQLBuilder
class. You can chain the SQLBuilder
methods to build your desired query. |
| createDelete
| Creates a DELETE query. Returns a function that returns an instance of the SQLBuilder
class. You can chain the SQLBuilder
methods to build your desired query. |
| createCount
| Creates a COUNT query. Returns a function that returns an instance of the SQLBuilder
class. You can chain the SQLBuilder
methods to build your desired query. |
| findOne
| Finds a single record. Returns an instance of the SQLBuilder
class with the findOne
method configured. |
| findAll
| Finds multiple records. Returns an instance of the SQLBuilder
class with the findAll
method configured. |
| remove
| Removes records based on conditions. Returns an instance of the SQLBuilder
class with the remove
method configured. |
| removeOne
| Removes a single record based on conditions. Returns an instance of the SQLBuilder
class with the removeOne
method configured. |
| patchSingleField
| Updates a single field in records based on conditions. Returns an instance of the SQLBuilder
class with the patchSingleField
method configured. |
| softDeleteOne
| Soft deletes a single record based on conditions. Returns an instance of the SQLBuilder
class with the softDeleteOne
method configured. |
| softDelete
| Soft deletes multiple records based on conditions. Returns an instance of the SQLBuilder
class with the softDelete
method configured. | |
The TableModel
class provides the following methods to perform database operations.
Methods that start with create
(e.g., createSelect
, createInsert
) return a function that returns an instance of the SQLBuilder
class. You can chain the SQLBuilder
methods to build your desired query.
Other methods, such as findOne
, return an instance of the SQLBuilder
class that is already configured with some chained methods. These methods act as wrapper functions for common CRUD operations and are not intended for further chaining.
createSelect
const selectUser = userModel.createSelect();
const result = await selectUser({
fields: ["user_id", "email", "nickname"],
})
.where({ user_id: 1 })
.executeQuery();
createInsert
const insertUser = userModel.createInsert();
const result = await insertUser({
data: { user_id: 1, email: "123@email.com", nickname: "John Doe" },
}).executeQuery();
createUpdate
const updateUser = userModel.createUpdate();
const result = await updateUser({
data: { nickname: "John Doe 2" },
where: { user_id: { "<=": 5 } },
})
.limit(2)
.executeQuery();
createDelete
const deleteUser = userModel.createDelete();
const result = await deleteUser({ where: { user_id: 1 } })
.limit(1)
.executeQuery();
createCount
const countResult = await countUser("user_id")
.where({ user_id: { "<": 2 } })
.executeQuery();
Common Parameters
The following table lists common parameters that many methods accept. Note that some parameters may be available for certain methods while others may not, as each method performs different operations. TypeScript will provide hints for the available parameters for each method.
Parameter | Type | Description |
---|
fields | Array | An array of strings specifying the columns to select. |
where | Object | An object specifying the conditions for the query. |
orderBy | Array | An array of objects specifying the columns to order by and the direction (ASC or DESC). |
limit | Number | A number specifying the maximum number of rows to return. |
offset | Number | A number specifying the offset of the first row to return. |
options | Object | An object specifying additional options for the query. Can be referenced in Update Options. |
findOne
const [user] = await userModel
.findOne({ where: { user_id: 1 } })
.executeQuery();
findAll
const users = await userModel
.findAll({
fields: ["user_id", "email"],
where: { is_active: true },
orderBy: [{ column: "user_id", direction: "ASC" }],
limit: 10,
offset: 0,
})
.executeQuery();
updateOne
const updatedOneUser = await userModel
.updateOne({
where: { user_id: 1 },
data: { email: "123@gmail.com" },
})
.executeQuery();
updateAll
const updateAllUsers = await userModel
.updateAll({
data: { nickname: "John Doe" },
where: { user_id: { "<=": 5 } },
options: { enableTimestamps: true, utimeField: "utime" },
})
.executeQuery();
insertRecord
const insertedUser = await userModel
.insertRecord({
data: { user_id: 1, email: "123@gmail.com", nickname: "John Doe" },
options: {
enableTimestamps: true,
ctimeField: "ctime",
utimeField: "utime",
},
})
.executeQuery();
removeOne
const deletedOneUser = await userModel
.removeOne({
where: { user_id: { ">": 1 } },
orderBy: [{ field: "user_id", direction: "ASC" }],
})
.executeQuery();
remove
const deletedAllUsers = await userModel
.remove({ where: { user_id: 1 } })
.executeQuery();
patchSingleField
const patchedActiveField = await userModel
.patchSingleField({
patchField: "is_active",
where: { user_id: 1 },
value: 1,
options: { enableTimestamps: true, utimeField: "utime" },
})
.executeQuery();
softDeleteOne
const softDeletedUser = await userModel
.softDeleteOne({
where: { user_id: 1 },
value: 1,
options: {
enableTimestamps: true,
deleteField: "is_deleted",
utimeField: "utime",
},
})
.executeQuery();
softDelete
const softDeletedUsers = await userModel
.softDelete({
where: { user_id: { ">": 1 } },
value: 1,
options: {
enableTimestamps: true,
deleteField: "is_deleted",
utimeField: "utime",
},
})
.executeQuery();
Changelog
Detailed changes for each version are documented in the CHANGELOG.md file.