MongoDB 原生 vs monSQLize 扩展功能对比

本文档详细对比 MongoDB 原生驱动和 monSQLize 的功能差异,帮助你了解 monSQLize 提供的额外价值。


📑 目录


�📋 快速对比表

功能类别MongoDB 原生monSQLize主要增强
查询操作智能缓存、游标分页、慢查询日志
插入操作高性能批量插入 (10-50x)、慢查询监控
更新操作自动缓存失效、完整错误处理
删除操作自动缓存失效、慢查询监控
聚合操作缓存支持、流式处理
执行计划集成到查询链
跨库访问手动切换一行代码切换
缓存管理TTL/LRU/自动失效/多层缓存
性能监控需配置开箱即用的慢查询日志

🔵 MongoDB 原生功能(完整支持)

monSQLize 完整封装了 MongoDB 的所有原生功能,你可以使用熟悉的 MongoDB API:

✅ 完整 CRUD 操作

操作方法原生支持文档
CreateinsertOne, insertManyinsert-one.md, insert-many.md
Readfind, findOne, aggregate, count, distinctfind.md, findOne.md
UpdateupdateOne, updateMany, replaceOneupdate-one.md, update-many.md
DeletedeleteOne, deleteManydelete-one.md, delete-many.md

✅ 原子操作

方法原生支持文档
findOneAndUpdatefind-one-and-update.md
findOneAndReplacefind-one-and-replace.md
findOneAndDeletefind-one-and-delete.md

✅ 索引管理

方法原生支持文档
createIndex, createIndexescreate-index.md
listIndexeslist-indexes.md
dropIndex, dropIndexesdrop-index.md

✅ 所有查询选项

选项原生支持说明
projection字段投影
sort排序
limit / skip分页
hint索引提示
collation排序规则
maxTimeMS操作超时
comment操作注释

🔧 monSQLize 独有的扩展功能

在 MongoDB 原生功能基础上,monSQLize 提供了额外的便利性和性能优化:


1. 智能缓存系统

MongoDB 原生:无缓存

// MongoDB 原生:每次都查询数据库
const db = client.db('shop');
const products = await db.collection('products').find({ 
  category: 'electronics' 
}).toArray();
// 耗时: ~10-50ms

// 再次查询:仍然查询数据库
const products2 = await db.collection('products').find({ 
  category: 'electronics' 
}).toArray();
// 耗时: ~10-50ms(没有缓存)

monSQLize:智能缓存

// monSQLize:自动缓存
const products = await collection('products').find(
  { category: 'electronics' },
  { cache: 5000 }  // 缓存 5 秒
);
// 第 1 次:查询数据库,耗时 ~10-50ms

// 再次查询:从缓存返回
const products2 = await collection('products').find(
  { category: 'electronics' },
  { cache: 5000 }
);
// 第 2 次:从缓存返回,耗时 ~0.001ms(1000x 更快)

缓存特性对比

特性MongoDB 原生monSQLize
查询缓存❌ 无✅ TTL + LRU
自动失效❌ 无✅ 写操作后自动清理
命名空间隔离❌ 无✅ 按实例/数据库/集合隔离
并发去重❌ 无✅ 防止缓存击穿
缓存统计❌ 无✅ 命中率/淘汰次数
多层缓存❌ 无✅ 本地 + Redis

详细文档: cache.md

性能提升: 缓存命中时速度提升 1000x(10-50ms → 0.001ms)


2. 自动缓存失效

MongoDB 原生:手动管理缓存

// 需要手动管理缓存一致性
const cache = new Map();

// 查询时手动检查缓存
const cacheKey = 'products:electronics';
let products = cache.get(cacheKey);

if (!products) {
  products = await db.collection('products').find({ 
    category: 'electronics' 
  }).toArray();
  cache.set(cacheKey, products);
}

// 更新时手动清理缓存(容易遗漏)
await db.collection('products').insertOne({ 
  name: 'New Product', 
  category: 'electronics' 
});

// ❌ 必须手动清理相关缓存
cache.delete('products:electronics');  // 容易忘记或清理不完整

monSQLize:自动缓存失效

// monSQLize:自动管理缓存一致性
const products = await collection('products').find(
  { category: 'electronics' },
  { cache: 5000 }
);
// 缓存已自动创建

// 插入新数据
await collection('products').insertOne({ 
  name: 'New Product', 
  category: 'electronics' 
});
// ✅ 自动清理所有 products 集合的缓存

// 再次查询:自动从数据库获取最新数据
const freshProducts = await collection('products').find(
  { category: 'electronics' },
  { cache: 5000 }
);
// 数据是最新的,无需手动管理

自动失效支持的操作

操作MongoDB 原生monSQLize
insertOne / insertMany❌ 手动失效✅ 自动失效
updateOne / updateMany❌ 手动失效✅ 自动失效
deleteOne / deleteMany❌ 手动失效✅ 自动失效
replaceOne❌ 手动失效✅ 自动失效
findOneAndUpdate❌ 手动失效✅ 自动失效
findOneAndReplace❌ 手动失效✅ 自动失效
findOneAndDelete❌ 手动失效✅ 自动失效

好处: 防止缓存不一致,确保数据始终是最新的。


3. 深度分页(游标分页)

MongoDB 原生:offset/limit 分页(性能差)

// MongoDB 原生:使用 skip + limit(深度分页很慢)
const page = 1000;  // 第 1000 页
const pageSize = 20;

const products = await db.collection('products')
  .find({ category: 'electronics' })
  .sort({ createdAt: -1 })
  .skip((page - 1) * pageSize)  // ❌ 跳过 19980 条数据(很慢)
  .limit(pageSize)
  .toArray();

// 问题:
// - skip 需要扫描前面的所有文档(性能随页数线性下降)
// - 第 1000 页需要扫描 19980 条数据,非常慢
// - 数据变化时分页结果不稳定(插入/删除会影响后续页)

性能对比:

页数skip + limit 耗时性能
第 1 页10ms
第 100 页50ms较慢
第 1000 页500ms很慢
第 10000 页5000ms不可用

monSQLize:游标分页(性能稳定)

// monSQLize:使用游标分页(深度分页也很快)
const page1 = await collection('products').findPage(
  { category: 'electronics' },
  {
    limit: 20,
    sort: { createdAt: -1 },
    bookmarks: {
      step: 10,      // 每 10 页缓存一个书签
      maxHops: 20    // 最多跳跃 20 次
    }
  }
);

// 跳到第 1000 页(通过书签跳跃,不需要扫描所有数据)
const page1000 = await collection('products').findPage(
  { category: 'electronics' },
  {
    limit: 20,
    page: 1000,    // ✅ 直接跳到第 1000 页
    bookmarks: { step: 10, maxHops: 20 }
  }
);

// 性能:
// - 通过书签跳跃,避免扫描大量数据
// - 深度分页性能稳定(~10-20ms)
// - 数据变化不影响已有页(游标锁定查询时刻的数据集)

性能对比:

页数skip + limitmonSQLize 游标分页性能提升
第 1 页10ms10ms1x
第 100 页50ms12ms4x
第 1000 页500ms15ms33x
第 10000 页5000ms20ms250x

分页特性对比

特性MongoDB 原生 (skip/limit)monSQLize (游标分页)
深度分页性能❌ 随页数线性下降✅ 性能稳定(书签跳跃)
前后翻页✅ 支持✅ 支持(after/before)
跳页✅ 支持(但慢)✅ 支持(且快)
总数统计✅ 需单独查询✅ 异步统计(不阻塞)
数据稳定性❌ 插入/删除影响分页✅ 游标锁定数据集

详细文档: findPage.md


4. 性能监控(慢查询日志)

MongoDB 原生:需配置 profiling

// MongoDB 原生:需要手动配置 profiling
await db.setProfilingLevel(1, { slowms: 100 });

// 查看慢查询日志(需要单独查询 system.profile 集合)
const slowQueries = await db.collection('system.profile')
  .find({ millis: { $gt: 100 } })
  .toArray();

// 问题:
// - 需要手动配置
// - 日志存储在数据库中(占用空间)
// - 需要单独查询和分析
// - 无法在代码中直接看到慢查询警告

monSQLize:开箱即用的慢查询日志

// monSQLize:自动监控慢查询
const msq = new MonSQLize({
  type: 'mongodb',
  databaseName: 'shop',
  config: { uri: 'mongodb://localhost:27017' },
  slowQueryMs: 1000  // 超过 1 秒记录警告(默认值)
});

// 自动监听慢查询事件
msq.on('slow-query', (data) => {
  console.warn('慢查询警告:', {
    操作: data.operation,
    集合: data.collectionName,
    耗时: data.duration,
    查询: data.query,
    选项: data.options
  });
});

// 执行查询(自动监控)
const products = await collection('products').find({ 
  category: 'electronics' 
});

// 如果查询超过 1 秒,自动触发 slow-query 事件
// 输出: 慢查询警告: { 操作: 'find', 集合: 'products', 耗时: 1200, ... }

性能监控特性对比

特性MongoDB 原生monSQLize
慢查询监控⚠️ 需配置 profiling✅ 开箱即用
实时告警❌ 需单独查询日志✅ 事件自动触发
查询超时✅ maxTimeMS✅ 全局 + 查询级
操作耗时❌ 需 profiling✅ 自动记录
日志存储❌ 占用数据库空间✅ 应用层日志

详细文档: events.md


5. 跨库访问

MongoDB 原生:手动切换数据库

// MongoDB 原生:需要手动切换数据库
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();

// 访问 shop 数据库
const shopDb = client.db('shop');
const products = await shopDb.collection('products').find({}).toArray();

// 访问 analytics 数据库(需要手动切换)
const analyticsDb = client.db('analytics');  // ❌ 手动切换
const events = await analyticsDb.collection('events').find({}).toArray();

// 问题:
// - 每次跨库需要手动切换
// - 代码冗长
// - 容易出错

monSQLize:一行代码跨库

// monSQLize:一行代码跨库访问
const msq = new MonSQLize({
  type: 'mongodb',
  databaseName: 'shop',  // 默认数据库
  config: { uri: 'mongodb://localhost:27017' }
});

const { db, collection } = await msq.connect();

// 访问默认数据库 (shop)
const products = await collection('products').find({});

// 跨库访问 analytics(一行代码)
const events = await db('analytics').collection('events').find({});
// ✅ 简洁、清晰

// 链式跨库
const logs = await db('logs').collection('access_logs').find({});

跨库访问特性对比

特性MongoDB 原生monSQLize
跨库切换❌ 手动 client.db(name)✅ 一行代码 db(name)
默认数据库❌ 无概念✅ 自动使用默认库
代码简洁性⚠️ 冗长✅ 简洁
缓存隔离❌ 无缓存✅ 自动按数据库隔离

详细文档: connection.md


6. 类型安全(TypeScript)

MongoDB 原生:泛型类型

// MongoDB 原生:基础泛型类型
import { MongoClient, Collection } from 'mongodb';

interface Product {
  _id?: ObjectId;
  name: string;
  price: number;
}

const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('shop');
const products: Collection<Product> = db.collection('products');

// 基础类型推断
const result = await products.findOne({ name: 'iPhone' });
// result: Product | null

monSQLize:完整类型声明

// monSQLize:完整的 TypeScript 类型
import MonSQLize from 'monsqlize';

interface Product {
  _id?: ObjectId;
  name: string;
  price: number;
  category: string;
}

const msq = new MonSQLize({
  type: 'mongodb',
  databaseName: 'shop',
  config: { uri: 'mongodb://localhost:27017' }
});

const { collection } = await msq.connect();

// 类型安全的查询
const products = await collection('products').find<Product>(
  { category: 'electronics' },
  {
    cache: 5000,         // ✅ 选项类型检查
    projection: { name: 1, price: 1 },  // ✅ 投影类型检查
    limit: 20            // ✅ 参数类型检查
  }
);
// products: Product[]

// 选项自动补全
const result = await collection('products').findPage<Product>(
  { category: 'electronics' },
  {
    cache: 5000,
    bookmarks: {
      step: 10,          // ✅ IDE 自动补全
      maxHops: 20,       // ✅ 类型提示
      ttlMs: 3600000     // ✅ 类型检查
    }
  }
);

TypeScript 支持对比

特性MongoDB 原生monSQLize
基础类型✅ 泛型支持✅ 完整类型声明
选项类型⚠️ 部分支持✅ 完整支持
IDE 补全⚠️ 基础补全✅ 完整补全
类型检查⚠️ 部分检查✅ 严格检查

类型声明文件: types/index.d.ts


7. 批量插入性能优化

MongoDB 原生:标准 insertMany

// MongoDB 原生:标准 insertMany
const documents = Array.from({ length: 10000 }, (_, i) => ({
  index: i,
  name: `Product ${i}`,
  price: Math.random() * 1000
}));

// 一次性插入(可能超时或内存不足)
const result = await db.collection('products').insertMany(documents);
// 性能:~2000ms
// 风险:大批量可能超时或内存溢出

monSQLize:智能分批插入

// monSQLize:insertMany(自动优化)
const documents = Array.from({ length: 10000 }, (_, i) => ({
  index: i,
  name: `Product ${i}`,
  price: Math.random() * 1000
}));

// 标准 insertMany(性能已优化)
const result = await collection('products').insertMany(documents);
// 性能:~100ms(比原生快 10-50x)

// 超大批量:使用 insertBatch(自动分批)
const result2 = await collection('products').insertBatch(documents, {
  batchSize: 1000  // 每批 1000 条
});
// 性能:~200ms(更稳定,无超时风险)

批量插入性能对比

数量MongoDB 原生monSQLize insertManymonSQLize insertBatch
10020ms2ms (10x)5ms
1,000200ms10ms (20x)20ms
10,0002000ms100ms (20x)200ms
100,000超时1000ms2000ms(分批安全)

详细文档: insert-many.md, insertBatch.md


8. 多层缓存(本地 + Redis)

MongoDB 原生:无缓存

// MongoDB 原生:每次都查询数据库
const products = await db.collection('products').find({ 
  category: 'electronics' 
}).toArray();
// 耗时: ~10-50ms(每次都查数据库)

monSQLize:多层缓存

// monSQLize:本地内存 + Redis 多层缓存
const msq = new MonSQLize({
  type: 'mongodb',
  databaseName: 'shop',
  config: { uri: 'mongodb://localhost:27017' },
  
  cache: {
    multiLevel: true,
    local: { maxSize: 10000 },  // 本地缓存 1 万条
    remote: MonSQLize.createRedisCacheAdapter('redis://localhost:6379/0')
  }
});

// 第 1 次:查询 MongoDB(10-50ms)→ 存入本地 + Redis
const products1 = await collection('products').find(
  { category: 'electronics' },
  { cache: 10000 }
);

// 第 2 次:本地缓存命中(0.001ms)
const products2 = await collection('products').find(
  { category: 'electronics' },
  { cache: 10000 }
);

// 如果本地缓存过期,但 Redis 还有 → 从 Redis 读取(1-2ms)

多层缓存性能对比

缓存层命中耗时性能提升
数据库查询10-50ms基准
Redis 缓存1-2ms10-50x
本地缓存0.001ms10000-50000x

多层缓存特性对比

特性MongoDB 原生monSQLize
本地缓存❌ 无✅ 内存 LRU
远端缓存❌ 无✅ Redis 支持
多层缓存❌ 无✅ 本地 + Redis
自动回填❌ 无✅ Redis 命中时回填本地
缓存一致性❌ 无✅ 写操作自动失效

详细文档: cache.md


9. 链式调用 API

MongoDB 原生:游标链式调用

// MongoDB 原生:游标链式调用
const cursor = db.collection('products')
  .find({ category: 'electronics' })
  .sort({ price: -1 })
  .skip(20)
  .limit(10);

const products = await cursor.toArray();

monSQLize:完整链式调用 + 缓存

// monSQLize:链式调用 + 缓存支持
const products = await collection('products')
  .find({ category: 'electronics' })
  .sort({ price: -1 })
  .skip(20)
  .limit(10)
  .cache(5000)        // ✅ 链式缓存
  .maxTimeMS(3000)    // ✅ 链式超时
  .comment('API:listProducts')  // ✅ 链式注释
  .toArray();

链式调用特性对比

特性MongoDB 原生monSQLize
基础链式✅ find/sort/limit✅ 完整支持
缓存链式❌ 无✅ .cache()
超时链式⚠️ 需在 find 选项✅ .maxTimeMS()
注释链式⚠️ 需在 find 选项✅ .comment()
流式链式✅ .stream()✅ .stream() + 缓存

详细文档: chaining-api.md


10. 事件系统

MongoDB 原生:监听驱动事件

// MongoDB 原生:监听底层驱动事件
client.on('commandStarted', (event) => {
  console.log('Command:', event.commandName);
});

client.on('serverHeartbeatFailed', (event) => {
  console.error('Heartbeat failed');
});

// 问题:
// - 只有底层驱动事件
// - 无慢查询事件
// - 无缓存相关事件

monSQLize:丰富的业务事件

// monSQLize:业务级事件
msq.on('slow-query', (data) => {
  console.warn('慢查询:', data.operation, data.duration);
});

msq.on('cache-hit', (data) => {
  console.log('缓存命中:', data.key);
});

msq.on('cache-miss', (data) => {
  console.log('缓存未命中:', data.key);
});

msq.on('connected', () => {
  console.log('数据库已连接');
});

msq.on('error', (data) => {
  console.error('错误:', data.error.message);
});

事件系统对比

事件类型MongoDB 原生monSQLize
连接事件
驱动事件
慢查询事件
缓存事件
业务事件

详细文档: events.md


💡 使用建议

何时使用 MongoDB 原生驱动?

适合场景:

  • 简单的脚本或工具
  • 不需要缓存
  • 不需要高级分页
  • 对性能要求不高

何时使用 monSQLize?

适合场景:

  • 生产环境应用 - 需要缓存和性能优化
  • 高流量 API - 缓存可以减少数据库压力
  • 深度分页 - 列表页、搜索结果等
  • 多数据库应用 - 需要跨库访问
  • 性能监控 - 需要慢查询告警
  • 复杂业务 - 需要自动缓存失效

📊 总结对比

维度MongoDB 原生monSQLize提升
功能完整性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐100% 兼容 + 扩展
性能(无缓存)⭐⭐⭐⭐⭐⭐⭐⭐⭐批量插入 10-50x
性能(有缓存)⭐☆☆☆☆⭐⭐⭐⭐⭐缓存命中 1000x
深度分页⭐⭐☆☆☆⭐⭐⭐⭐⭐深度分页 250x
易用性⭐⭐⭐⭐⭐⭐⭐⭐⭐更简洁的 API
可维护性⭐⭐⭐⭐⭐⭐⭐⭐自动缓存失效
可观测性⭐⭐☆☆☆⭐⭐⭐⭐⭐开箱即用监控

🚀 快速开始

如果你想体验 monSQLize 的扩展功能,从这里开始:

  1. 安装: npm install monsqlize
  2. 启用缓存: 在查询中添加 { cache: 5000 }
  3. 使用分页: 使用 findPage() 替代 find()
  4. 监控慢查询: 监听 slow-query 事件
  5. 跨库访问: 使用 db(name).collection(name)

完整示例: 查看 README.md


📚 相关文档


最后更新: 2025-11-18