@hemia/db-connector
v0.0.8
Published
Hemia Database Conector
Readme
@hemia/db-connector
Conector unificado para bases de datos SQL, NoSQL y OLAP, diseñado para facilitar operaciones comunes como conexión, transacciones, queries y manipulación de datos. Ideal para aplicaciones Node.js que requieren una interfaz abstracta para distintos motores de base de datos.
Instalación
npm install @hemia/db-connectorBases de Datos Soportadas
🗄️ SQL (OLTP - Online Transaction Processing)
Bases de datos relacionales optimizadas para transacciones y operaciones CRUD.
- ✅ MySQL - Base de datos relacional de código abierto
- ✅ PostgreSQL - Base de datos relacional avanzada con soporte JSON
- ✅ Microsoft SQL Server (MSSQL) - Base de datos empresarial de Microsoft
Casos de uso:
- Sistemas transaccionales (e-commerce, banking)
- Aplicaciones empresariales (ERP, CRM)
- Gestión de usuarios y autenticación
- Aplicaciones que requieren integridad referencial
📄 NoSQL (Document Store)
Bases de datos orientadas a documentos para datos no estructurados.
- ✅ MongoDB - Base de datos de documentos JSON flexible y escalable
Casos de uso:
- Aplicaciones con esquemas flexibles
- Gestión de contenido (CMS)
- Perfiles de usuario complejos
- Catálogos de productos
- Logs y eventos en formato JSON
- Aplicaciones en tiempo real
📊 OLAP (Online Analytical Processing)
Bases de datos columnares optimizadas para análisis y consultas agregadas.
- ✅ ClickHouse - Base de datos columnar de alta velocidad para análisis en tiempo real
Casos de uso:
- Análisis de logs y trazas (APM, Observability)
- Métricas y monitoreo en tiempo real
- Business Intelligence y Data Warehousing
- Análisis de eventos y comportamiento de usuarios
- Procesamiento de grandes volúmenes de datos
- Dashboards analíticos de alto rendimiento
Uso rápido
MongoDB
import { MongoDBConnector } from '@hemia/db-connector';
const mongo = new MongoDBConnector({
host: 'localhost',
user: 'admin',
password: '1234',
database: 'mydb',
});
await mongo.connect();
const docs = await mongo.find(MyModel, { status: 'active' });SQL (MySQL/MSSQL/PostgreSQL)
import { DBConnector } from '@hemia/db-connector';
import { DBSQLType } from '@hemia/db-connector/types/DBSQLTypes';
const dbConnector = DBConnector.getInstance();
const sql = dbConnector.getEngine(DBSQLType.MySQL, {
host: 'localhost',
user: 'root',
password: 'pass',
database: 'mydb',
dialect: 'mysql'
});
await sql.connect();
const rows = await sql.select('users', { where: { active: true } });
// Transacciones
await sql.withTransaction(async (transaction) => {
await sql.insert('orders', { userId: 1, total: 100 }, { transaction });
await sql.update('users', { id: 1 }, { balance: 500 }, { transaction });
});ClickHouse (OLAP)
import { DBConnector } from '@hemia/db-connector';
import { DBOLAPType } from '@hemia/db-connector/types/OLAPTypes';
const dbConnector = DBConnector.getInstance();
const clickhouse = dbConnector.getEngine(DBOLAPType.ClickHouse, {
host: 'http://localhost:8123',
user: 'default',
password: '',
database: 'analytics',
});
await clickhouse.connect();
// Insertar datos (JSONEachRow por defecto)
await clickhouse.insert({
table: 'traces',
values: [
{ trace_id: '123', service_name: 'api', duration_ms: 45 },
{ trace_id: '124', service_name: 'db', duration_ms: 120 }
]
});
// Insertar con formato CSV
await clickhouse.insert({
table: 'traces',
values: '125,"cache",30\n126,"queue",85',
format: 'CSV'
});
// Buscar con filtros
const traces = await clickhouse.find('traces', {
service_name: 'api',
error: false
});
// Query personalizada para análisis
const stats = await clickhouse.query(`
SELECT
service_name,
count() as total_requests,
avg(duration_ms) as avg_duration,
max(duration_ms) as max_duration
FROM traces
WHERE start_time >= now() - INTERVAL 1 HOUR
GROUP BY service_name
ORDER BY total_requests DESC
`);Uso con DBConnector (Recomendado)
El patrón recomendado es usar DBConnector como punto de entrada único:
import { DBConnector } from '@hemia/db-connector';
import { DBSQLType, DBNoSQLType, DBOLAPType } from '@hemia/db-connector';
const dbConnector = DBConnector.getInstance();
// Obtener motor SQL
const mysql = dbConnector.getEngine(DBSQLType.MySQL, credentials);
// Obtener motor NoSQL
const mongo = dbConnector.getEngine(DBNoSQLType.MongoDB, credentials);
// Obtener motor OLAP
const clickhouse = dbConnector.getEngine(DBOLAPType.ClickHouse, credentials);Características destacadas
MongoDBConnector (NoSQL)
- Conexión y desconexión automáticas
- Transacciones con rollback (
withTransaction) - CRUD genérico (
create,find,findOne,update,delete, etc.) - Operaciones avanzadas:
aggregate,findAllFromMultipleModels - Soporte para modelos Mongoose
- Manejo automático de sesiones
Ejemplo de uso avanzado:
// Aggregate pipeline
const results = await mongo.aggregate(UserModel, [
{ $match: { active: true } },
{ $group: { _id: '$country', total: { $sum: 1 } } }
]);
// Transacciones
await mongo.withTransaction(async (session) => {
await mongo.create(UserModel, { name: 'John' }, session);
await mongo.update(UserModel, { _id: userId }, { status: 'active' }, session);
});SequelizeSqlConnector (SQL)
- Operaciones CRUD:
select,insert,update,delete - Transacciones con soporte completo de Sequelize (
withTransaction) - Query SQL libre con
query()para consultas complejas - Manejo de errores y mapeo de códigos SQLSTATE (
createDatabaseError) - Soporte para stored procedures
- Conexión a MySQL, PostgreSQL, MSSQL
Ejemplo de uso avanzado:
// Query con stored procedure
const result = await sql.query('CALL get_user_stats(:userId)', {
replacements: { userId: 123 },
type: QueryTypes.SELECT
});
// Transacciones
await sql.withTransaction(async (transaction) => {
await sql.insert('orders', orderData, { transaction });
await sql.update('inventory', { productId: 1 }, { stock: 10 }, { transaction });
});ClickHouseConnector (OLAP)
- Conexión optimizada para análisis de alto rendimiento
- Múltiples formatos de inserción:
JSONEachRow,CSV,TabSeparated, etc. - Método
find()con filtros para búsquedas rápidas - Query SQL libre para análisis complejos
- Ideal para procesamiento de grandes volúmenes de datos
- Soporte para columnas calculadas (MATERIALIZED)
Ejemplo de uso avanzado:
// Insertar millones de registros eficientemente
await clickhouse.insert({
table: 'events',
values: largeDataArray, // Array con millones de registros
format: 'JSONEachRow'
});
// Análisis en tiempo real
const metrics = await clickhouse.query(`
SELECT
toStartOfMinute(timestamp) as minute,
countIf(status = 200) as success,
countIf(status >= 400) as errors,
quantile(0.95)(response_time) as p95_latency
FROM http_logs
WHERE timestamp >= now() - INTERVAL 1 HOUR
GROUP BY minute
ORDER BY minute DESC
`);
// Búsqueda con filtros múltiples
const errorTraces = await clickhouse.find('traces', {
service_name: 'payment-api',
error: true,
duration_ms: 1000 // Mayor a 1 segundo
});Tipos esperados de configuración
interface CredentialsConnection {
host: string;
port?: number;
user?: string;
password?: string;
database: string;
dialect?: 'mysql' | 'mssql' | 'postgres';
logging?: boolean;
}Arquitectura y Patrones de Uso
Lambda Architecture: Combinando SQL, NoSQL y OLAP
Una arquitectura común es usar diferentes bases de datos para diferentes propósitos:
// 1. OLTP (MySQL/PostgreSQL) - Transacciones en tiempo real
const mysql = dbConnector.getEngine(DBSQLType.MySQL, mysqlCredentials);
await mysql.insert('orders', { userId: 123, amount: 99.99 });
// 2. NoSQL (MongoDB) - Datos flexibles y documentos
const mongo = dbConnector.getEngine(DBNoSQLType.MongoDB, mongoCredentials);
await mongo.create(ProductModel, {
name: 'Laptop',
specs: { ram: '16GB', cpu: 'i7' } // Esquema flexible
});
// 3. OLAP (ClickHouse) - Análisis y reportes
const clickhouse = dbConnector.getEngine(DBOLAPType.ClickHouse, clickhouseCredentials);
await clickhouse.insert({
table: 'order_analytics',
values: [{
order_id: orderId,
user_id: 123,
amount: 99.99,
timestamp: new Date()
}]
});Casos de Uso por Tipo de Base de Datos
🗄️ SQL (MySQL/PostgreSQL/MSSQL)
Cuándo usar:
- Necesitas transacciones ACID
- Relaciones complejas entre entidades
- Integridad referencial crítica
- Consultas con JOINs
Ejemplos:
- Sistema de facturación
- Gestión de inventario
- Sistema de usuarios y permisos
- Carrito de compras
📄 NoSQL (MongoDB)
Cuándo usar:
- Esquemas variables o en evolución
- Necesitas escalar horizontalmente
- Documentos JSON complejos
- Alto volumen de escrituras
Ejemplos:
- Catálogo de productos con atributos variables
- Perfiles de usuario con datos personalizados
- Sistema de logs y auditoría
- Gestión de contenido (CMS)
📊 OLAP (ClickHouse)
Cuándo usar:
- Análisis de grandes volúmenes de datos
- Consultas agregadas complejas
- Necesitas latencias de milisegundos en análisis
- Datos de series temporales
Ejemplos:
- Observabilidad y APM (traces, logs, métricas)
- Análisis de comportamiento de usuarios
- Dashboards de BI en tiempo real
- Análisis de eventos y clickstream
- Monitoreo de infraestructura
Ejemplo Completo: Sistema de E-commerce con Observabilidad
import { DBConnector, DBSQLType, DBNoSQLType, DBOLAPType } from '@hemia/db-connector';
const connector = DBConnector.getInstance();
// 1. Base de datos transaccional (MySQL)
const mysql = connector.getEngine(DBSQLType.MySQL, {
host: 'localhost',
database: 'ecommerce',
user: 'root',
password: 'pass'
});
// 2. Base de datos de documentos (MongoDB)
const mongo = connector.getEngine(DBNoSQLType.MongoDB, {
host: 'localhost',
database: 'ecommerce_content'
});
// 3. Base de datos analítica (ClickHouse)
const clickhouse = connector.getEngine(DBOLAPType.ClickHouse, {
host: 'http://localhost:8123',
database: 'analytics'
});
// Procesar orden
async function processOrder(orderData) {
const startTime = Date.now();
try {
// 1. Guardar orden en MySQL (transaccional)
await mysql.withTransaction(async (tx) => {
const order = await mysql.insert('orders', orderData, { transaction: tx });
await mysql.update('inventory',
{ productId: orderData.productId },
{ stock: { decrement: 1 } },
{ transaction: tx }
);
});
// 2. Guardar detalles enriquecidos en MongoDB
await mongo.create(OrderDetailsModel, {
orderId: orderData.id,
userPreferences: orderData.preferences,
metadata: orderData.metadata
});
// 3. Registrar evento en ClickHouse para análisis
await clickhouse.insert({
table: 'order_events',
values: [{
event_type: 'order_created',
order_id: orderData.id,
user_id: orderData.userId,
amount: orderData.amount,
duration_ms: Date.now() - startTime,
timestamp: new Date(),
success: true
}]
});
} catch (error) {
// Registrar error en ClickHouse
await clickhouse.insert({
table: 'order_events',
values: [{
event_type: 'order_failed',
order_id: orderData.id,
error_message: error.message,
duration_ms: Date.now() - startTime,
timestamp: new Date(),
success: false
}]
});
throw error;
}
}
// Análisis de órdenes en tiempo real
async function getOrderStats() {
return await clickhouse.query(`
SELECT
toStartOfHour(timestamp) as hour,
countIf(success = true) as successful_orders,
countIf(success = false) as failed_orders,
avg(amount) as avg_order_value,
quantile(0.95)(duration_ms) as p95_duration
FROM order_events
WHERE timestamp >= now() - INTERVAL 24 HOUR
GROUP BY hour
ORDER BY hour DESC
`);
}Licencia
MIT
Autor
Hemia Technologies
