场景配方

目录导航

只连接 MongoDB

import MonSQLize from 'monsqlize';

const db = new MonSQLize({
    type: 'mongodb',
    databaseName: 'app',
    config: { uri: 'mongodb://127.0.0.1:27017' },
});

await db.connect();

const users = db.collection('users');
await users.insertOne({ name: 'Ada', createdAt: new Date() });

await db.close();

适合先验证连接、CRUD 和包入口。缺少 config.uri 会抛出 INVALID_CONFIG,未 connect() 直接访问数据会抛出 NOT_CONNECTED

开启内存缓存

import MonSQLize from 'monsqlize';

const db = new MonSQLize({
    type: 'mongodb',
    databaseName: 'app',
    config: { uri: 'mongodb://127.0.0.1:27017' },
    cache: {
        enabled: true,
        ttl: 60_000,
        maxEntries: 5_000,
        enableStats: true,
    },
});

await db.connect();

内存缓存不需要额外服务,适合单进程或本地快速验证。

开启 Redis 二级缓存与分布式失效

import MonSQLize from 'monsqlize';

const db = new MonSQLize({
    type: 'mongodb',
    databaseName: 'app',
    config: { uri: 'mongodb://127.0.0.1:27017' },
    cache: {
        memory: { maxEntries: 5_000, ttl: 30_000 },
        redis: { url: 'redis://127.0.0.1:6379', timeoutMs: 300 },
        distributed: {
            redisUrl: 'redis://127.0.0.1:6379',
            channel: 'app:cache:invalidate',
        },
    },
});

await db.connect();

ioredis 已随 monsqlize 默认安装;这里需要配置的是 Redis 地址和是否启用分布式失效,而不是再安装依赖。

通过 SSH 隧道连接内网 MongoDB

import MonSQLize from 'monsqlize';

const db = new MonSQLize({
    type: 'mongodb',
    databaseName: 'app',
    config: {
        uri: 'mongodb://mongo.internal:27017/app',
        ssh: {
            host: 'bastion.example.com',
            username: 'deploy',
            privateKeyPath: '~/.ssh/id_rsa',
        },
    },
});

await db.connect();

ssh2 已随 monsqlize 默认安装。只要传入 config.ssh,运行时会建立本地隧道并把 MongoDB 连接转发到内网地址。

配置多连接池

import MonSQLize from 'monsqlize';

const db = new MonSQLize({
    type: 'mongodb',
    databaseName: 'app',
    pools: [
        { name: 'primary', uri: 'mongodb://primary:27017/app', role: 'primary' },
        { name: 'analytics', uri: 'mongodb://analytics:27017/app', role: 'analytics', tags: ['reporting'] },
    ],
    poolStrategy: 'auto',
    poolFallback: { enabled: true, fallbackStrategy: 'secondary' },
});

await db.connect();
const reports = db.pool('analytics').collection('reports');

连接池配置错误会抛出 INVALID_CONFIG;指定不存在的池会抛出 POOL_NOT_FOUND;所有池不可用会抛出 INVALID_OPERATION

使用业务锁

await db.withLock('inventory:SKU123', async () => {
    const inventory = db.collection('inventory');
    const item = await inventory.findOne({ sku: 'SKU123' });
    if (item?.stock > 0) {
        await inventory.updateOne({ sku: 'SKU123' }, { $inc: { stock: -1 } });
    }
}, {
    ttl: 10_000,
    retryTimes: 3,
    retryDelay: 100,
});

单进程场景默认使用内存锁;跨实例场景可传入 Redis 相关配置启用分布式锁能力。

启用 Model 层

import MonSQLize, { Model } from 'monsqlize';

Model.define('users', {
    schema: (dsl) => dsl({
        name: 'string:1-64!',
        email: 'email!',
    }),
});

const db = new MonSQLize({
    type: 'mongodb',
    databaseName: 'app',
    config: { uri: 'mongodb://127.0.0.1:27017' },
});

await db.connect();
const User = db.model('users');
await User.insertOne({ name: 'Ada', email: 'ada@example.com' });

schema-dsl 已随 monsqlize 默认安装。只有应用代码直接导入 schema-dsl 时,才需要在应用自己的依赖里声明它。

按错误码排障

import { ErrorCodes } from 'monsqlize';

try {
    await db.connect();
} catch (error) {
    const code = (error as { code?: string }).code;
    if (code === ErrorCodes.INVALID_CONFIG) {
        console.error('检查 MonSQLize 构造配置');
    } else if (code === ErrorCodes.CONNECTION_FAILED) {
        console.error('检查 MongoDB 网络、认证和 URI');
    } else {
        throw error;
    }
}

更多错误码与处理建议见 error-codes.md