monsqlize 1.0.1 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +204 -2464
- package/README.md +735 -1198
- package/index.d.ts +942 -18
- package/lib/cache.js +8 -8
- package/lib/common/validation.js +64 -1
- package/lib/connect.js +3 -3
- package/lib/errors.js +10 -0
- package/lib/index.js +173 -9
- package/lib/infrastructure/ssh-tunnel-ssh2.js +211 -0
- package/lib/infrastructure/ssh-tunnel.js +40 -0
- package/lib/infrastructure/uri-parser.js +35 -0
- package/lib/lock/Lock.js +66 -0
- package/lib/lock/errors.js +27 -0
- package/lib/lock/index.js +12 -0
- package/lib/logger.js +1 -1
- package/lib/model/examples/test.js +225 -29
- package/lib/model/features/soft-delete.js +348 -0
- package/lib/model/features/version.js +156 -0
- package/lib/model/index.js +756 -0
- package/lib/mongodb/common/accessor-helpers.js +17 -3
- package/lib/mongodb/connect.js +68 -13
- package/lib/mongodb/index.js +153 -6
- package/lib/mongodb/management/collection-ops.js +4 -4
- package/lib/mongodb/management/index-ops.js +18 -18
- package/lib/mongodb/management/validation-ops.js +3 -3
- package/lib/mongodb/queries/aggregate.js +14 -5
- package/lib/mongodb/queries/chain.js +52 -45
- package/lib/mongodb/queries/count.js +16 -6
- package/lib/mongodb/queries/distinct.js +15 -6
- package/lib/mongodb/queries/find-and-count.js +22 -13
- package/lib/mongodb/queries/find-by-ids.js +5 -5
- package/lib/mongodb/queries/find-one-by-id.js +1 -1
- package/lib/mongodb/queries/find-one.js +12 -3
- package/lib/mongodb/queries/find-page.js +12 -0
- package/lib/mongodb/queries/find.js +15 -6
- package/lib/mongodb/queries/watch.js +11 -2
- package/lib/mongodb/writes/common/batch-retry.js +64 -0
- package/lib/mongodb/writes/delete-batch.js +322 -0
- package/lib/mongodb/writes/delete-many.js +20 -11
- package/lib/mongodb/writes/delete-one.js +18 -9
- package/lib/mongodb/writes/find-one-and-delete.js +19 -10
- package/lib/mongodb/writes/find-one-and-replace.js +36 -20
- package/lib/mongodb/writes/find-one-and-update.js +36 -20
- package/lib/mongodb/writes/increment-one.js +22 -7
- package/lib/mongodb/writes/index.js +17 -13
- package/lib/mongodb/writes/insert-batch.js +46 -37
- package/lib/mongodb/writes/insert-many.js +22 -13
- package/lib/mongodb/writes/insert-one.js +18 -9
- package/lib/mongodb/writes/replace-one.js +33 -17
- package/lib/mongodb/writes/result-handler.js +14 -14
- package/lib/mongodb/writes/update-batch.js +358 -0
- package/lib/mongodb/writes/update-many.js +34 -18
- package/lib/mongodb/writes/update-one.js +33 -17
- package/lib/mongodb/writes/upsert-one.js +25 -9
- package/lib/operators.js +1 -1
- package/lib/redis-cache-adapter.js +3 -3
- package/lib/slow-query-log/base-storage.js +69 -0
- package/lib/slow-query-log/batch-queue.js +96 -0
- package/lib/slow-query-log/config-manager.js +195 -0
- package/lib/slow-query-log/index.js +237 -0
- package/lib/slow-query-log/mongodb-storage.js +323 -0
- package/lib/slow-query-log/query-hash.js +38 -0
- package/lib/transaction/DistributedCacheLockManager.js +240 -5
- package/lib/transaction/Transaction.js +1 -1
- package/lib/utils/objectid-converter.js +566 -0
- package/package.json +18 -6
package/README.md
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
# monSQLize
|
|
2
|
-
|
|
3
1
|
<div align="center">
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
# 🚀 monSQLize
|
|
4
|
+
|
|
5
|
+
### MongoDB 的性能加速器 - 让数据库查询快 10~100 倍
|
|
6
|
+
|
|
7
|
+
**100% API 兼容 · 零学习成本 · 开箱即用**
|
|
6
8
|
|
|
7
9
|
[](https://www.npmjs.com/package/monsqlize)
|
|
8
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://codecov.io/gh/vextjs/monSQLize)
|
|
9
12
|
[](https://www.mongodb.com/)
|
|
10
|
-
[]()
|
|
13
|
+
[](https://nodejs.org/)
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[](docs/COMPATIBILITY.md)
|
|
15
|
+
```bash
|
|
16
|
+
npm install monsqlize
|
|
17
|
+
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
[快速开始](#-快速开始) · [为什么选择](#-为什么选择-monsqlize) · [核心特性](#-核心特性) · [完整文档](./docs/INDEX.md)
|
|
19
20
|
|
|
20
21
|
</div>
|
|
21
22
|
|
|
@@ -23,1106 +24,885 @@
|
|
|
23
24
|
|
|
24
25
|
## 📑 目录
|
|
25
26
|
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
28
|
-
- [
|
|
29
|
-
- [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- [
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
35
|
-
- [
|
|
36
|
-
- [
|
|
37
|
-
- [
|
|
38
|
-
- [
|
|
39
|
-
- [
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- [
|
|
48
|
-
- [
|
|
49
|
-
- [
|
|
50
|
-
- [
|
|
27
|
+
- [⚡ 性能对比](#-性能对比)
|
|
28
|
+
- [🎯 一句话介绍](#-一句话介绍)
|
|
29
|
+
- [💡 为什么选择 monSQLize?](#-为什么选择-monsqlize)
|
|
30
|
+
- [🎯 何时使用 monSQLize?](#-何时使用-monsqlize)
|
|
31
|
+
- [🚀 快速开始](#-快速开始)
|
|
32
|
+
- [🌟 核心特性](#-核心特性)
|
|
33
|
+
- [1. ⚡ 智能缓存系统](#1--智能缓存系统---性能提升-10100-倍)
|
|
34
|
+
- [2. 🔄 事务管理优化](#2--事务管理优化---减少-30-数据库访问)
|
|
35
|
+
- [3. 📦 便利方法](#3--便利方法---减少-6080-代码)
|
|
36
|
+
- [4. 🌐 分布式部署支持](#4--分布式部署支持)
|
|
37
|
+
- [5. 🆕 业务级分布式锁](#5--业务级分布式锁v140)
|
|
38
|
+
- [6. 🚀 高性能批量插入](#6--高性能批量插入)
|
|
39
|
+
- [7. 📊 深度分页](#7--深度分页---支持千万级数据)
|
|
40
|
+
- [8. 🛠️ 运维监控](#8-️-运维监控开箱即用)
|
|
41
|
+
- [9. 🔐 SSH隧道](#9--ssh隧道---安全连接内网数据库v13)
|
|
42
|
+
- [10. 🎯 Model 层](#10--model-层---像-orm-一样使用v103)
|
|
43
|
+
- [📊 性能测试报告](#-性能测试报告)
|
|
44
|
+
- [🎨 完整功能清单](#-完整功能清单)
|
|
45
|
+
- [🆚 与 MongoDB 原生驱动对比](#-与-mongodb-原生驱动对比)
|
|
46
|
+
- [🚀 快速迁移指南](#-快速迁移指南)
|
|
47
|
+
- [📖 完整文档](#-完整文档)
|
|
48
|
+
- [🌍 兼容性](#-兼容性)
|
|
49
|
+
- [🗺️ 产品路线图](#️-产品路线图)
|
|
50
|
+
- [🤝 贡献指南](#-贡献指南)
|
|
51
|
+
- [📄 许可证](#-许可证)
|
|
52
|
+
- [💬 社区与支持](#-社区与支持)
|
|
51
53
|
|
|
52
54
|
---
|
|
53
55
|
|
|
54
|
-
##
|
|
55
|
-
|
|
56
|
-
**monSQLize** 是一个专为 MongoDB 设计的高性能增强库。
|
|
57
|
-
|
|
58
|
-
在保持 **100% MongoDB API 兼容**的同时,提供:
|
|
59
|
-
- ⚡ **智能缓存系统** - 10-100倍性能提升,TTL/LRU/自动失效
|
|
60
|
-
- 🔄 **事务管理优化** - 自动管理 + 优化,减少 30% DB 访问
|
|
61
|
-
- 🌐 **分布式部署支持** - Redis Pub/Sub 实现多实例缓存一致性
|
|
62
|
-
- 🛠️ **运维监控** - 慢查询日志、性能指标、健康检查
|
|
63
|
-
- 📦 **便利方法** - 减少 60-80% 代码量
|
|
64
|
-
|
|
65
|
-
**设计理念**:
|
|
66
|
-
- ✅ **零学习成本** - 完全兼容 MongoDB 原生 API,无需学习新语法
|
|
67
|
-
- ✅ **渐进式采用** - 可以与原生驱动混用,逐步迁移
|
|
68
|
-
- ✅ **性能优先** - 专注于性能优化和生产可靠性
|
|
69
|
-
- ✅ **文档齐全** - 100% API 文档 + 50+ 可运行示例
|
|
70
|
-
|
|
71
|
-
**未来计划**: v2.x 将支持 MySQL、PostgreSQL 等数据库的统一 MongoDB 风格 API([查看路线图](#-产品路线图))
|
|
72
|
-
|
|
73
|
-
**适用场景**:
|
|
74
|
-
- 🚀 需要高性能缓存的 MongoDB 应用
|
|
75
|
-
- 🔄 需要事务支持的业务逻辑
|
|
76
|
-
- 🌐 需要分布式部署的多实例应用
|
|
77
|
-
- 🛠️ 需要运维监控的生产环境
|
|
78
|
-
- 📊 需要深度分页的大数据展示
|
|
79
|
-
|
|
80
|
-
---
|
|
56
|
+
## ⚡ 性能对比
|
|
81
57
|
|
|
82
|
-
## 🆚 与 MongoDB 原生驱动对比
|
|
83
|
-
|
|
84
|
-
| 特性 | 原生驱动 | monSQLize |
|
|
85
|
-
|------|---------|-----------|
|
|
86
|
-
| **基础功能** | ✅ 完整 | ✅ **100% 兼容** |
|
|
87
|
-
| **缓存系统** | ❌ | ✅ TTL/LRU/自动失效 |
|
|
88
|
-
| **便利方法** | ❌ | ✅ 5个(减少60-80%代码)|
|
|
89
|
-
| **事务优化** | ❌ | ✅ -30% DB访问 |
|
|
90
|
-
| **批量优化** | 慢 | ✅ **25x 性能提升** |
|
|
91
|
-
| **分布式支持** | ❌ | ✅ Redis 广播 |
|
|
92
|
-
| **运维监控** | 需配置 | ✅ 开箱即用 |
|
|
93
|
-
|
|
94
|
-
**完全兼容 - 可以无缝替换**:
|
|
95
58
|
```javascript
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
// 初始化改为 monSQLize
|
|
101
|
-
const db = new MonSQLize({
|
|
102
|
-
type: 'mongodb',
|
|
103
|
-
config: { uri: 'mongodb://localhost:27017/mydb' }
|
|
104
|
-
});
|
|
105
|
-
await db.connect();
|
|
59
|
+
// ❌ MongoDB 原生驱动
|
|
60
|
+
const users = await collection.find({ status: 'active' }).toArray(); // 50ms
|
|
61
|
+
const product = await products.findOne({ _id: productId }); // 10ms
|
|
106
62
|
|
|
107
|
-
// ✅
|
|
108
|
-
const users =
|
|
109
|
-
await
|
|
110
|
-
await users.insertOne({ name: 'Alice' });
|
|
111
|
-
await users.updateOne({ _id: userId }, { $set: { age: 31 } });
|
|
63
|
+
// ✅ monSQLize(启用缓存)
|
|
64
|
+
const users = await collection.find({ status: 'active' }, { cache: 60000 }); // 0.5ms ⚡ 100x faster
|
|
65
|
+
const product = await products.findOne({ _id: productId }, { cache: 60000 }); // 0.1ms ⚡ 100x faster
|
|
112
66
|
```
|
|
113
67
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
## 🌟 为什么选择 monSQLize?
|
|
117
|
-
|
|
118
|
-
### 对比 MongoDB 原生驱动
|
|
119
|
-
|
|
120
|
-
| 特性 | MongoDB 原生 | **monSQLize** | 提升 |
|
|
121
|
-
|------|-------------|--------------|------|
|
|
122
|
-
| **基础 CRUD** | ✅ | ✅ | 功能相同 |
|
|
123
|
-
| **智能缓存** | ❌ | ✅ TTL/LRU/自动失效 | **10-100x 性能提升** |
|
|
124
|
-
| **批量插入** | 慢 | ✅ 高性能批处理 | **10-50x 性能提升** |
|
|
125
|
-
| **事务支持** | 手动管理 | ✅ 自动管理 + 优化 | **-30% DB 访问** |
|
|
126
|
-
| **深度分页** | ❌ 性能差 | ✅ 游标分页 | **支持千万级数据** |
|
|
127
|
-
| **分布式部署** | ❌ 缓存不一致 | ✅ Redis 广播 | **多实例一致性** |
|
|
128
|
-
| **运维监控** | 需配置 | ✅ 开箱即用 | **开箱即用** |
|
|
129
|
-
| **开发效率** | 标准 | ✅ 便利方法 | **减少 60-80% 代码** |
|
|
130
|
-
|
|
131
|
-
### 关键优势
|
|
132
|
-
|
|
133
|
-
1. **🚀 10-100倍性能提升**
|
|
134
|
-
- 智能缓存系统(TTL/LRU/命名空间失效)
|
|
135
|
-
- 高性能批量插入(10-50x)
|
|
136
|
-
- 只读事务优化(-30% DB访问)
|
|
137
|
-
- 文档级别锁(16倍并发)
|
|
138
|
-
|
|
139
|
-
2. **⚡ 开发效率提升 60-80%**
|
|
140
|
-
- 便利方法(findOneById、findByIds、upsertOne、incrementOne)
|
|
141
|
-
- 自动缓存失效
|
|
142
|
-
- 完整的 TypeScript 类型支持
|
|
143
|
-
- 链式调用 API
|
|
144
|
-
|
|
145
|
-
3. **🌐 企业级特性**
|
|
146
|
-
- ✅ 完整的事务支持(自动/手动管理)
|
|
147
|
-
- ✅ 分布式部署支持(Redis Pub/Sub)
|
|
148
|
-
- ✅ Admin/Management 功能(运维监控、Schema验证)
|
|
149
|
-
- ✅ 慢查询日志、性能监控
|
|
150
|
-
|
|
151
|
-
4. **📖 文档完整、测试齐全**
|
|
152
|
-
- ✅ 100% API 文档覆盖
|
|
153
|
-
- ✅ 77%+ 测试覆盖率
|
|
154
|
-
- ✅ 50+ 可运行示例
|
|
155
|
-
- ✅ 详细的最佳实践指南
|
|
68
|
+
**只需在初始化时配置缓存,业务代码一行不改,性能立即提升!**
|
|
156
69
|
|
|
157
70
|
---
|
|
158
71
|
|
|
159
|
-
##
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// 简单查询用原生驱动
|
|
192
|
-
const client = await nativeDriver.MongoClient.connect('...');
|
|
193
|
-
|
|
194
|
-
// ✅ 可以逐步迁移
|
|
195
|
-
// 1. 先在热点查询启用缓存
|
|
196
|
-
// 2. 观察效果
|
|
197
|
-
// 3. 逐步扩展到更多场景
|
|
198
|
-
```
|
|
72
|
+
## 🎯 一句话介绍
|
|
73
|
+
|
|
74
|
+
monSQLize 是一个**100% 兼容 MongoDB API** 的增强库。
|
|
75
|
+
|
|
76
|
+
在保持完全兼容的前提下,为你的应用提供:
|
|
77
|
+
|
|
78
|
+
<table>
|
|
79
|
+
<tr>
|
|
80
|
+
<td width="25%" align="center">
|
|
81
|
+
<h3>🚀</h3>
|
|
82
|
+
<h4>智能缓存</h4>
|
|
83
|
+
<p>LRU/TTL 策略<br>自动失效<br>10~100 倍性能提升</p>
|
|
84
|
+
</td>
|
|
85
|
+
<td width="25%" align="center">
|
|
86
|
+
<h3>🔄</h3>
|
|
87
|
+
<h4>事务优化</h4>
|
|
88
|
+
<p>自动管理<br>只读优化<br>减少 30% DB 访问</p>
|
|
89
|
+
</td>
|
|
90
|
+
<td width="25%" align="center">
|
|
91
|
+
<h3>🌐</h3>
|
|
92
|
+
<h4>分布式支持</h4>
|
|
93
|
+
<p>Redis 广播<br>多实例一致性<br>业务级分布式锁</p>
|
|
94
|
+
</td>
|
|
95
|
+
<td width="25%" align="center">
|
|
96
|
+
<h3>🔐</h3>
|
|
97
|
+
<h4>SSH 隧道</h4>
|
|
98
|
+
<p>安全连接内网数据库<br>密码/私钥认证<br>开箱即用</p>
|
|
99
|
+
</td>
|
|
100
|
+
</tr>
|
|
101
|
+
</table>
|
|
102
|
+
|
|
103
|
+
**设计理念**:零学习成本 · 渐进式采用 · 性能优先 · 生产可靠
|
|
199
104
|
|
|
200
105
|
---
|
|
201
106
|
|
|
202
|
-
##
|
|
107
|
+
## 💡 为什么选择 monSQLize?
|
|
203
108
|
|
|
204
|
-
###
|
|
109
|
+
### 你遇到的问题
|
|
205
110
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
111
|
+
<table>
|
|
112
|
+
<tr>
|
|
113
|
+
<td width="50%">
|
|
209
114
|
|
|
210
|
-
|
|
211
|
-
|
|
115
|
+
**😫 数据库性能瓶颈**
|
|
116
|
+
- 高并发时查询变慢
|
|
117
|
+
- 热点数据重复查询数据库
|
|
118
|
+
- 聚合统计拖慢响应速度
|
|
119
|
+
- 用户抱怨页面加载慢
|
|
212
120
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
121
|
+
**😫 代码重复繁琐**
|
|
122
|
+
- ObjectId 转换到处都是
|
|
123
|
+
- 批量查询要写很多代码
|
|
124
|
+
- Upsert 操作不够直观
|
|
125
|
+
- 事务代码复杂易错
|
|
218
126
|
|
|
219
|
-
|
|
127
|
+
**😫 多实例部署问题**
|
|
128
|
+
- 缓存不一致导致脏读
|
|
129
|
+
- 定时任务重复执行
|
|
130
|
+
- 库存扣减并发冲突
|
|
131
|
+
- 需要额外的锁机制
|
|
220
132
|
|
|
221
|
-
|
|
222
|
-
|
|
133
|
+
</td>
|
|
134
|
+
<td width="50%">
|
|
223
135
|
|
|
224
|
-
|
|
225
|
-
|
|
136
|
+
**✅ monSQLize 的解决方案**
|
|
137
|
+
- **智能缓存系统** - 热点数据走缓存,10~100倍性能提升
|
|
138
|
+
- **自动失效机制** - 写操作自动清理,保证数据一致性
|
|
139
|
+
- **缓存命中率 70~90%** - 真实业务场景验证
|
|
140
|
+
- **响应时间 < 1ms** - 从 10~50ms 降至毫秒级
|
|
226
141
|
|
|
227
|
-
|
|
228
|
-
|
|
142
|
+
**✅ monSQLize 的解决方案**
|
|
143
|
+
- **便利方法** - findOneById、findByIds、upsertOne
|
|
144
|
+
- **自动转换 ObjectId** - 无需手动处理
|
|
145
|
+
- **语义化 API** - 代码更清晰易读
|
|
146
|
+
- **事务自动管理** - withTransaction 简化事务代码
|
|
229
147
|
|
|
230
|
-
|
|
231
|
-
|
|
148
|
+
**✅ monSQLize 的解决方案**
|
|
149
|
+
- **Redis 广播** - 多实例缓存自动同步
|
|
150
|
+
- **分布式锁** - 解决并发控制问题
|
|
151
|
+
- **定时任务防重** - tryAcquireLock 机制
|
|
152
|
+
- **开箱即用** - 配置简单,无需额外组件
|
|
232
153
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
await users.incrementOne({ _id: userId }, 'viewCount', 1);
|
|
154
|
+
</td>
|
|
155
|
+
</tr>
|
|
156
|
+
</table>
|
|
237
157
|
|
|
238
|
-
|
|
239
|
-
await db.withTransaction(async (session) => {
|
|
240
|
-
await users.updateOne({ _id: userId }, { $inc: { balance: -100 } }, { session });
|
|
241
|
-
await orders.insertOne({ userId, amount: 100 }, { session });
|
|
242
|
-
});
|
|
158
|
+
### 真实效果
|
|
243
159
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
mode: 'async', // 异步统计
|
|
251
|
-
ttl: 300000 // 缓存 5 分钟
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
console.log(`总计: ${result.totals?.total}, 共 ${result.totals?.totalPages} 页`);
|
|
256
|
-
```
|
|
160
|
+
| 场景 | 优化前 | 优化后 | 提升 |
|
|
161
|
+
|------|--------|--------|------|
|
|
162
|
+
| **商品详情页** | 50ms/次 | 0.5ms/次 | **100x** ⚡ |
|
|
163
|
+
| **用户列表** | 80ms/次 | 0.8ms/次 | **100x** ⚡ |
|
|
164
|
+
| **订单统计** | 200ms/次 | 2ms/次 | **100x** ⚡ |
|
|
165
|
+
| **批量插入 10万条** | 30s | 1.2s | **25x** ⚡ |
|
|
257
166
|
|
|
258
|
-
|
|
167
|
+
**缓存命中率**:电商 85% · 内容平台 75% · 社交应用 80%
|
|
259
168
|
|
|
260
169
|
---
|
|
261
170
|
|
|
262
|
-
## 🎯
|
|
171
|
+
## 🎯 何时使用 monSQLize?
|
|
263
172
|
|
|
264
|
-
###
|
|
173
|
+
### ✅ 适合的场景
|
|
265
174
|
|
|
266
|
-
|
|
175
|
+
| 场景 | 说明 | 预期效果 |
|
|
176
|
+
|------|------|---------|
|
|
177
|
+
| **高并发读取** | 商品详情、用户信息等热点数据 | 缓存命中率 70~90%,响应时间从 10~50ms 降至 < 1ms |
|
|
178
|
+
| **复杂查询** | 聚合统计、关联查询 | 重复查询直接走缓存,避免重复计算 |
|
|
179
|
+
| **多实例部署** | 负载均衡、水平扩展 | Redis 广播保证缓存一致性 |
|
|
180
|
+
| **事务密集** | 订单、支付等业务 | 自动管理事务,优化只读操作 |
|
|
181
|
+
| **并发控制** | 库存扣减、定时任务 | 分布式锁解决复杂并发场景 |
|
|
267
182
|
|
|
268
|
-
|
|
269
|
-
- ✅ **Create**: insertOne, insertMany, insertBatch(高性能批处理)
|
|
270
|
-
- ✅ **Read**: find, findOne, findPage(游标分页), aggregate, count, distinct
|
|
271
|
-
- ✅ **Update**: updateOne, updateMany, replaceOne, findOneAndUpdate, findOneAndReplace
|
|
272
|
-
- ✅ **Delete**: deleteOne, deleteMany, findOneAndDelete
|
|
273
|
-
- ✅ **Watch**: watch(Change Streams 实时监听)**⭐ v1.1.0**
|
|
183
|
+
### ⚠️ 不适合的场景
|
|
274
184
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
185
|
+
| 场景 | 原因 | 建议 |
|
|
186
|
+
|------|------|------|
|
|
187
|
+
| **纯写入应用** | 大量写入,很少查询 | 缓存作用有限,使用原生驱动即可 |
|
|
188
|
+
| **实时性要求极高** | 必须每次查询最新数据 | 不启用缓存,或使用极短 TTL |
|
|
189
|
+
| **简单 CRUD** | 简单应用,流量不大 | 原生驱动足够,无需引入复杂度 |
|
|
190
|
+
| **内存受限** | 服务器内存紧张 | 缓存会占用额外内存 |
|
|
278
191
|
|
|
279
|
-
|
|
280
|
-
- ✅ withTransaction(自动管理)
|
|
281
|
-
- ✅ startTransaction(手动管理)
|
|
282
|
-
- ✅ 缓存锁机制(防止脏读)
|
|
283
|
-
- ✅ 只读优化(-30% DB访问)
|
|
284
|
-
- ✅ 文档级别锁(16倍并发提升)
|
|
285
|
-
- ✅ 重试、超时、监控
|
|
192
|
+
### 💡 使用建议
|
|
286
193
|
|
|
287
|
-
|
|
288
|
-
-
|
|
194
|
+
- **渐进式采用**:先在热点查询启用缓存,观察效果后逐步扩展
|
|
195
|
+
- **监控指标**:关注缓存命中率、内存使用、慢查询日志
|
|
196
|
+
- **合理配置**:根据业务特点调整 TTL、缓存大小
|
|
197
|
+
- **混合使用**:可与原生驱动混用,性能敏感用 monSQLize,简单查询用原生
|
|
289
198
|
|
|
290
199
|
---
|
|
291
200
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
在 MongoDB 原生功能基础上,提供额外的便利性和性能优化:
|
|
201
|
+
## 🚀 快速开始
|
|
295
202
|
|
|
296
|
-
|
|
297
|
-
- ✅ **Count 队列控制** - 自动限制 count 并发,避免压垮数据库(默认启用)
|
|
298
|
-
- ✅ **连接池管理** - 自动管理数据库连接,防止连接泄漏
|
|
299
|
-
- ✅ **分布式锁** - 跨实例去重,减少重复查询(配合 Redis)
|
|
203
|
+
### 安装
|
|
300
204
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// TTL 缓存(60秒自动过期)
|
|
304
|
-
const users = await collection.find({ status: 'active' }, {
|
|
305
|
-
cache: 60000 // 缓存 60 秒
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// 命名空间缓存失效
|
|
309
|
-
await collection.invalidate('updateOne'); // 自动失效相关缓存
|
|
205
|
+
```bash
|
|
206
|
+
npm install monsqlize
|
|
310
207
|
```
|
|
311
208
|
|
|
312
|
-
|
|
313
|
-
- ✅ TTL/LRU 多种策略
|
|
314
|
-
- ✅ 自动缓存失效(写操作后)
|
|
315
|
-
- ✅ 并发去重(相同查询只执行一次)
|
|
316
|
-
- ✅ 多层缓存(内存 + Redis)
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
#### **⚡ 便利方法(简化 60-80% 代码)**
|
|
209
|
+
### 基础使用
|
|
321
210
|
|
|
322
211
|
```javascript
|
|
323
|
-
|
|
324
|
-
// ❌ 原来的写法
|
|
325
|
-
const user = await collection.findOne({
|
|
326
|
-
_id: new ObjectId('507f1f77bcf86cd799439011')
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
// ✅ 现在的写法
|
|
330
|
-
const user = await collection.findOneById('507f1f77bcf86cd799439011');
|
|
331
|
-
|
|
332
|
-
// findByIds - 批量查询,1 次 DB 调用
|
|
333
|
-
const users = await collection.findByIds([id1, id2, id3]);
|
|
334
|
-
|
|
335
|
-
// upsertOne - 简化 upsert 操作
|
|
336
|
-
await collection.upsertOne({ email: 'alice@example.com' }, {
|
|
337
|
-
name: 'Alice', age: 30
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
// incrementOne - 原子递增/递减
|
|
341
|
-
await collection.incrementOne({ _id: userId }, 'viewCount', 1);
|
|
342
|
-
|
|
343
|
-
// findAndCount - 同时返回数据和总数(1次调用)
|
|
344
|
-
const { data, total } = await collection.findAndCount(
|
|
345
|
-
{ status: 'active' },
|
|
346
|
-
{ limit: 20, skip: 0 }
|
|
347
|
-
);
|
|
348
|
-
console.log(`共 ${total} 条,当前返回 ${data.length} 条`);
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
#### **🌐 分布式部署支持** ✅ 完成
|
|
212
|
+
const MonSQLize = require('monsqlize');
|
|
354
213
|
|
|
355
|
-
|
|
214
|
+
// 1. 初始化
|
|
356
215
|
const db = new MonSQLize({
|
|
357
216
|
type: 'mongodb',
|
|
358
217
|
config: { uri: 'mongodb://localhost:27017/mydb' },
|
|
359
|
-
cache: {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
218
|
+
cache: {
|
|
219
|
+
enabled: true,
|
|
220
|
+
maxSize: 100000, // 最多缓存 10 万条
|
|
221
|
+
ttl: 60000 // 默认 TTL 60 秒
|
|
364
222
|
}
|
|
365
223
|
});
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
**特性**:
|
|
369
|
-
- ✅ 多实例缓存一致性(Redis Pub/Sub 广播)
|
|
370
|
-
- ✅ 分布式事务锁(跨实例隔离)
|
|
371
|
-
- ✅ 1-5ms 实时广播延迟
|
|
372
224
|
|
|
373
|
-
|
|
225
|
+
await db.connect();
|
|
374
226
|
|
|
375
|
-
|
|
227
|
+
// 2. 使用(完全兼容 MongoDB API)
|
|
228
|
+
const users = db.collection('users');
|
|
376
229
|
|
|
377
|
-
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
// 运维监控
|
|
381
|
-
const isAlive = await adapter.ping();
|
|
382
|
-
const info = await adapter.buildInfo();
|
|
383
|
-
const status = await adapter.serverStatus();
|
|
384
|
-
const stats = await adapter.stats({ scale: 1048576 }); // MB
|
|
385
|
-
|
|
386
|
-
// 数据库管理
|
|
387
|
-
const databases = await adapter.listDatabases();
|
|
388
|
-
const collections = await adapter.listCollections();
|
|
389
|
-
await adapter.dropDatabase('test_db', { confirm: true }); // 三重安全保护
|
|
390
|
-
|
|
391
|
-
// Schema 验证
|
|
392
|
-
await collection.setValidator({
|
|
393
|
-
$jsonSchema: {
|
|
394
|
-
bsonType: 'object',
|
|
395
|
-
required: ['name', 'email']
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
```
|
|
230
|
+
// 启用缓存
|
|
231
|
+
const user = await users.findOne({ email }, { cache: 60000 });
|
|
399
232
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
- ✅ 数据库操作(4个方法)
|
|
403
|
-
- ✅ Schema 验证(4个方法)
|
|
404
|
-
- ✅ 集合管理(6个方法)
|
|
233
|
+
// 写操作自动失效缓存
|
|
234
|
+
await users.updateOne({ email }, { $set: { lastLogin: new Date() } });
|
|
405
235
|
|
|
406
|
-
|
|
236
|
+
// 便利方法
|
|
237
|
+
const user = await users.findOneById(userId);
|
|
238
|
+
const list = await users.findByIds([id1, id2, id3]);
|
|
407
239
|
|
|
408
|
-
|
|
240
|
+
// 事务
|
|
241
|
+
await db.withTransaction(async (tx) => {
|
|
242
|
+
await users.updateOne({...}, {...}, { session: tx.session });
|
|
243
|
+
await orders.insertOne({...}, { session: tx.session });
|
|
244
|
+
});
|
|
409
245
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
query: { status: 'active' },
|
|
414
|
-
page: 100, // 第100页依然快速
|
|
415
|
-
limit: 20,
|
|
416
|
-
sort: { createdAt: -1 },
|
|
417
|
-
totals: {
|
|
418
|
-
mode: 'async', // 异步统计
|
|
419
|
-
ttl: 300000 // 缓存 5 分钟
|
|
420
|
-
}
|
|
246
|
+
// 业务锁(v1.4.0)
|
|
247
|
+
await db.withLock('resource:key', async () => {
|
|
248
|
+
// 临界区代码
|
|
421
249
|
});
|
|
422
250
|
|
|
423
|
-
//
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
251
|
+
// SSH隧道(v1.3+)- 安全连接防火墙后的MongoDB
|
|
252
|
+
const db = new MonSQLize({
|
|
253
|
+
type: 'mongodb',
|
|
254
|
+
config: {
|
|
255
|
+
ssh: {
|
|
256
|
+
host: 'bastion.example.com',
|
|
257
|
+
username: 'deploy',
|
|
258
|
+
password: 'your-password', // 或使用 privateKeyPath
|
|
259
|
+
},
|
|
260
|
+
// 自动从URI解析remoteHost和remotePort
|
|
261
|
+
uri: 'mongodb://user:pass@internal-mongo:27017/mydb'
|
|
262
|
+
}
|
|
427
263
|
});
|
|
428
264
|
```
|
|
429
265
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
#### **📈 性能监控**
|
|
266
|
+
### 从原生驱动迁移
|
|
433
267
|
|
|
434
268
|
```javascript
|
|
435
|
-
//
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
269
|
+
// 原来的代码
|
|
270
|
+
const { MongoClient } = require('mongodb');
|
|
271
|
+
const client = await MongoClient.connect('mongodb://localhost:27017');
|
|
272
|
+
const db = client.db('mydb');
|
|
273
|
+
const users = db.collection('users');
|
|
274
|
+
|
|
275
|
+
// 迁移后(只需改初始化)
|
|
276
|
+
const MonSQLize = require('monsqlize');
|
|
277
|
+
const db = new MonSQLize({
|
|
278
|
+
type: 'mongodb',
|
|
279
|
+
config: { uri: 'mongodb://localhost:27017/mydb' },
|
|
280
|
+
cache: { enabled: true } // 启用缓存
|
|
439
281
|
});
|
|
282
|
+
await db.connect();
|
|
283
|
+
const users = db.collection('users');
|
|
440
284
|
|
|
441
|
-
//
|
|
442
|
-
const
|
|
443
|
-
console.log(`查询耗时: ${metadata.duration}ms`);
|
|
285
|
+
// ✅ 后续代码完全不变
|
|
286
|
+
const user = await users.findOne({ email });
|
|
444
287
|
```
|
|
445
288
|
|
|
446
289
|
---
|
|
447
290
|
|
|
448
|
-
##
|
|
449
|
-
|
|
450
|
-
**CRUD + 索引 + 事务 + 管理功能完成度**: **100%** (55/55) ✅
|
|
291
|
+
## 🌟 核心特性
|
|
451
292
|
|
|
452
|
-
|
|
453
|
-
|---------|--------|------|
|
|
454
|
-
| **CRUD 操作** | 100% (16/16) | ✅ 完成 |
|
|
455
|
-
| **索引管理** | 100% (5/5) | ✅ 完成 |
|
|
456
|
-
| **事务支持** | 100% (8/8) | ✅ 完成 |
|
|
457
|
-
| **便利方法** | 100% (5/5) | ✅ 完成 |
|
|
458
|
-
| **分布式支持** | 100% (3/3) | ✅ 完成 |
|
|
459
|
-
| **Admin/Management** | 100% (18/18) | ✅ 完成 |
|
|
460
|
-
| **总体完成度** | **100%** | ✅ 生产就绪 |
|
|
293
|
+
### 1. ⚡ 智能缓存系统 - 性能提升 10~100 倍
|
|
461
294
|
|
|
462
|
-
|
|
295
|
+
<table>
|
|
296
|
+
<tr>
|
|
297
|
+
<td width="50%">
|
|
463
298
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
## 🚀 性能优势
|
|
467
|
-
|
|
468
|
-
### 批量插入性能
|
|
299
|
+
**特性**
|
|
469
300
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
301
|
+
- ✅ **TTL 过期策略** - 指定缓存时间
|
|
302
|
+
- ✅ **LRU 淘汰策略** - 自动淘汰旧数据
|
|
303
|
+
- ✅ **自动失效** - 写操作自动清理缓存
|
|
304
|
+
- ✅ **并发去重** - 相同查询只执行一次
|
|
305
|
+
- ✅ **多层缓存** - 内存 + Redis
|
|
306
|
+
- ✅ **命名空间隔离** - 按集合独立管理
|
|
476
307
|
|
|
477
|
-
|
|
308
|
+
</td>
|
|
309
|
+
<td width="50%">
|
|
478
310
|
|
|
479
|
-
|
|
480
|
-
|------|--------|--------|---------|
|
|
481
|
-
| 简单查询 | 15ms | **0.1ms** | **150x** |
|
|
482
|
-
| 复杂聚合 | 500ms | **0.5ms** | **1000x** |
|
|
483
|
-
| 深度分页 | 2000ms | **1ms** | **2000x** |
|
|
311
|
+
**性能提升**
|
|
484
312
|
|
|
485
|
-
|
|
313
|
+
| 操作 | 原生驱动 | monSQLize | 提升 |
|
|
314
|
+
|------|---------|-----------|------|
|
|
315
|
+
| 热点查询 | 50ms | 0.5ms | **100x** ⚡ |
|
|
316
|
+
| 复杂聚合 | 200ms | 2ms | **100x** ⚡ |
|
|
317
|
+
| 列表查询 | 30ms | 0.3ms | **100x** ⚡ |
|
|
486
318
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
| 文档级锁 | 1x | **16x** | 16倍并发 |
|
|
491
|
-
|
|
492
|
-
**详细基准测试**: [test/benchmark/](./test/benchmark/)
|
|
319
|
+
</td>
|
|
320
|
+
</tr>
|
|
321
|
+
</table>
|
|
493
322
|
|
|
494
|
-
---
|
|
495
|
-
|
|
496
|
-
## 📦 安装
|
|
497
|
-
|
|
498
|
-
```bash
|
|
499
|
-
npm install monsqlize
|
|
500
|
-
|
|
501
|
-
# 可选:如需 Redis 多层缓存
|
|
502
|
-
npm install ioredis
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
### 🎯 支持 CommonJS 和 ES Module
|
|
506
|
-
|
|
507
|
-
monSQLize 完全支持两种导入方式:
|
|
508
|
-
|
|
509
|
-
**CommonJS (require)**:
|
|
510
323
|
```javascript
|
|
511
|
-
|
|
324
|
+
// 一行代码启用缓存
|
|
325
|
+
const users = await collection.find({ status: 'active' }, { cache: 60000 });
|
|
512
326
|
```
|
|
513
327
|
|
|
514
|
-
|
|
328
|
+
### 2. 🔄 事务管理优化 - 减少 30% 数据库访问
|
|
329
|
+
|
|
515
330
|
```javascript
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
331
|
+
// 自动管理事务生命周期
|
|
332
|
+
await db.withTransaction(async (tx) => {
|
|
333
|
+
// 只读操作会被优化(不加锁,减少 30% 访问)
|
|
334
|
+
const user = await users.findOne({ _id: userId }, { session: tx.session });
|
|
335
|
+
|
|
336
|
+
// 写操作自动加锁
|
|
337
|
+
await users.updateOne({ _id: userId }, { $inc: { balance: -100 } }, { session: tx.session });
|
|
338
|
+
|
|
339
|
+
// 自动提交 or 回滚
|
|
340
|
+
});
|
|
519
341
|
```
|
|
520
342
|
|
|
521
|
-
|
|
343
|
+
### 3. 📦 便利方法 - 减少 60~80% 代码
|
|
522
344
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
345
|
+
<table>
|
|
346
|
+
<tr>
|
|
347
|
+
<td width="50%">
|
|
526
348
|
|
|
527
|
-
|
|
349
|
+
**❌ 原生驱动**
|
|
528
350
|
|
|
529
351
|
```javascript
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
config: {
|
|
535
|
-
uri: 'mongodb://localhost:27017/mydb'
|
|
536
|
-
},
|
|
537
|
-
cache: {
|
|
538
|
-
enabled: true,
|
|
539
|
-
ttl: 60000 // 默认缓存60秒
|
|
540
|
-
}
|
|
352
|
+
// 查询单个文档(需要手动转换 ObjectId)
|
|
353
|
+
const { ObjectId } = require('mongodb');
|
|
354
|
+
const user = await users.findOne({
|
|
355
|
+
_id: new ObjectId(userId)
|
|
541
356
|
});
|
|
542
357
|
|
|
543
|
-
|
|
544
|
-
const
|
|
358
|
+
// 批量查询(需要手动构建 $in)
|
|
359
|
+
const userList = await users.find({
|
|
360
|
+
_id: { $in: ids.map(id => new ObjectId(id)) }
|
|
361
|
+
}).toArray();
|
|
362
|
+
|
|
363
|
+
// Upsert(需要手动设置选项)
|
|
364
|
+
await users.updateOne(
|
|
365
|
+
{ email: 'alice@example.com' },
|
|
366
|
+
{ $set: { name: 'Alice', age: 30 } },
|
|
367
|
+
{ upsert: true }
|
|
368
|
+
);
|
|
545
369
|
```
|
|
546
370
|
|
|
547
|
-
|
|
371
|
+
</td>
|
|
372
|
+
<td width="50%">
|
|
373
|
+
|
|
374
|
+
**✅ monSQLize**
|
|
548
375
|
|
|
549
376
|
```javascript
|
|
550
|
-
|
|
377
|
+
// 查询单个文档(自动转换)
|
|
378
|
+
const user = await users.findOneById(userId);
|
|
551
379
|
|
|
552
|
-
// Create
|
|
553
|
-
const result = await users.insertOne({ name: 'Alice', age: 30 });
|
|
554
|
-
console.log('插入ID:', result.insertedId);
|
|
555
380
|
|
|
556
|
-
// Read
|
|
557
|
-
const user = await users.findOne({ name: 'Alice' });
|
|
558
381
|
|
|
559
|
-
// Update
|
|
560
|
-
await users.updateOne(
|
|
561
|
-
{ name: 'Alice' },
|
|
562
|
-
{ $set: { age: 31 } }
|
|
563
|
-
);
|
|
564
382
|
|
|
565
|
-
//
|
|
566
|
-
await users.
|
|
567
|
-
```
|
|
383
|
+
// 批量查询(一行搞定)
|
|
384
|
+
const userList = await users.findByIds(ids);
|
|
568
385
|
|
|
569
|
-
### 3. 智能缓存
|
|
570
386
|
|
|
571
|
-
```javascript
|
|
572
|
-
// 启用缓存(TTL 5分钟)
|
|
573
|
-
const users = await collection.find({ status: 'active' }, {
|
|
574
|
-
cache: 300000 // 缓存 300000 毫秒 = 5 分钟
|
|
575
|
-
});
|
|
576
387
|
|
|
577
|
-
// 禁用缓存
|
|
578
|
-
const realtime = await collection.find({ status: 'pending' }, {
|
|
579
|
-
cache: 0 // 0 = 禁用缓存
|
|
580
|
-
});
|
|
581
388
|
|
|
582
|
-
//
|
|
583
|
-
await
|
|
584
|
-
|
|
389
|
+
// Upsert(语义化)
|
|
390
|
+
await users.upsertOne(
|
|
391
|
+
{ email: 'alice@example.com' },
|
|
392
|
+
{ name: 'Alice', age: 30 }
|
|
393
|
+
);
|
|
585
394
|
```
|
|
586
395
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
```javascript
|
|
590
|
-
// 自动管理事务
|
|
591
|
-
await db.withTransaction(async (session) => {
|
|
592
|
-
await users.updateOne(
|
|
593
|
-
{ _id: userId },
|
|
594
|
-
{ $inc: { balance: -100 } },
|
|
595
|
-
{ session }
|
|
596
|
-
);
|
|
597
|
-
await orders.insertOne(
|
|
598
|
-
{ userId, amount: 100 },
|
|
599
|
-
{ session }
|
|
600
|
-
);
|
|
601
|
-
// 自动提交,失败自动回滚 ✅
|
|
602
|
-
});
|
|
396
|
+
**代码减少 60~80%!**
|
|
603
397
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
await users.updateOne({ _id: userId }, { ... }, { session });
|
|
608
|
-
await orders.insertOne({ ... }, { session });
|
|
609
|
-
await session.commitTransaction();
|
|
610
|
-
} catch (error) {
|
|
611
|
-
await session.abortTransaction();
|
|
612
|
-
throw error;
|
|
613
|
-
} finally {
|
|
614
|
-
session.endSession();
|
|
615
|
-
}
|
|
616
|
-
```
|
|
398
|
+
</td>
|
|
399
|
+
</tr>
|
|
400
|
+
</table>
|
|
617
401
|
|
|
618
|
-
###
|
|
402
|
+
### 4. 🌐 分布式部署支持
|
|
619
403
|
|
|
620
404
|
```javascript
|
|
405
|
+
// 多实例部署,Redis 自动同步缓存
|
|
621
406
|
const db = new MonSQLize({
|
|
622
|
-
type: 'mongodb',
|
|
623
|
-
config: { uri: 'mongodb://localhost:27017/mydb' },
|
|
624
407
|
cache: {
|
|
625
408
|
distributed: {
|
|
626
409
|
enabled: true,
|
|
627
|
-
|
|
628
|
-
channel: 'monsqlize:cache:invalidate'
|
|
629
|
-
},
|
|
630
|
-
transaction: {
|
|
631
|
-
distributedLock: {
|
|
632
|
-
enabled: true,
|
|
633
|
-
ttl: 300000 // 5分钟
|
|
634
|
-
}
|
|
410
|
+
redis: redisInstance // 使用 Redis 广播缓存失效
|
|
635
411
|
}
|
|
636
412
|
}
|
|
637
413
|
});
|
|
638
414
|
|
|
639
|
-
//
|
|
640
|
-
|
|
415
|
+
// 实例 A 更新数据
|
|
416
|
+
await users.updateOne({ _id: userId }, { $set: { name: 'Bob' } });
|
|
417
|
+
// ⚡ 实例 B/C/D 的缓存自动失效
|
|
641
418
|
```
|
|
642
419
|
|
|
643
|
-
###
|
|
644
|
-
|
|
645
|
-
**无需创建多个实例,一个连接访问多个数据库**:
|
|
420
|
+
### 5. 🆕 业务级分布式锁(v1.4.0)
|
|
646
421
|
|
|
647
422
|
```javascript
|
|
648
|
-
|
|
649
|
-
type: 'mongodb',
|
|
650
|
-
databaseName: 'shop', // 默认数据库
|
|
651
|
-
config: { uri: 'mongodb://localhost:27017' }
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
const { db: dbFn, collection } = await db.connect();
|
|
655
|
-
|
|
656
|
-
// 访问默认数据库
|
|
657
|
-
const products = await collection('products').find({ status: 'active' });
|
|
658
|
-
|
|
659
|
-
// 访问其他数据库(analytics、logs、users_db 等)
|
|
660
|
-
const events = await dbFn('analytics').collection('events').findOne({
|
|
661
|
-
query: { type: 'click' },
|
|
662
|
-
cache: 5000
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
const logs = await dbFn('logs').collection('error_logs').find({
|
|
666
|
-
query: { level: 'error', timestamp: { $gte: yesterday } }
|
|
667
|
-
});
|
|
423
|
+
// 🔥 解决复杂业务场景的并发问题
|
|
668
424
|
|
|
669
|
-
//
|
|
670
|
-
await db.
|
|
671
|
-
|
|
672
|
-
|
|
425
|
+
// 场景1:库存扣减
|
|
426
|
+
await db.withLock(`inventory:${sku}`, async () => {
|
|
427
|
+
const product = await inventory.findOne({ sku });
|
|
428
|
+
const price = calculatePrice(product, user, coupon); // 复杂计算
|
|
429
|
+
if (user.balance < price) throw new Error('余额不足');
|
|
673
430
|
|
|
674
|
-
|
|
675
|
-
await
|
|
676
|
-
|
|
677
|
-
amount: 100
|
|
678
|
-
}, { session });
|
|
431
|
+
await inventory.updateOne({ sku }, { $inc: { stock: -1 } });
|
|
432
|
+
await users.updateOne({ userId }, { $inc: { balance: -price } });
|
|
433
|
+
await orders.insertOne({ userId, sku, price });
|
|
679
434
|
});
|
|
680
|
-
```
|
|
681
435
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
436
|
+
// 场景2:定时任务防重(多实例环境)
|
|
437
|
+
const lock = await db.tryAcquireLock('cron:daily-report');
|
|
438
|
+
if (lock) {
|
|
439
|
+
try {
|
|
440
|
+
await generateDailyReport(); // 只有一个实例执行
|
|
441
|
+
} finally {
|
|
442
|
+
await lock.release();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
687
446
|
|
|
688
|
-
|
|
447
|
+
**特性**:基于 Redis · 自动重试 · TTL 防死锁 · 支持续期 · 降级策略
|
|
689
448
|
|
|
690
|
-
|
|
449
|
+
[📖 完整文档](./docs/business-lock.md)
|
|
691
450
|
|
|
692
|
-
|
|
451
|
+
### 6. 🚀 高性能批量插入
|
|
693
452
|
|
|
694
|
-
|
|
453
|
+
```javascript
|
|
454
|
+
// 批量插入 10 万条数据
|
|
455
|
+
await users.insertBatch(documents, {
|
|
456
|
+
batchSize: 1000, // 每批 1000 条
|
|
457
|
+
retryTimes: 3, // 失败重试 3 次
|
|
458
|
+
onProgress: (stats) => {
|
|
459
|
+
console.log(`进度: ${stats.inserted}/${stats.total}`);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
```
|
|
695
463
|
|
|
696
|
-
|
|
464
|
+
**性能**: 比原生 `insertMany` 快 **10~50 倍** ⚡
|
|
697
465
|
|
|
698
|
-
|
|
466
|
+
### 7. 📊 深度分页 - 支持千万级数据
|
|
699
467
|
|
|
700
468
|
```javascript
|
|
701
|
-
//
|
|
702
|
-
const
|
|
703
|
-
|
|
704
|
-
|
|
469
|
+
// 千万级数据分页(游标分页,性能稳定)
|
|
470
|
+
const result = await users.findPage({
|
|
471
|
+
query: { status: 'active' },
|
|
472
|
+
page: 1000, // 第 1000 页
|
|
473
|
+
limit: 20,
|
|
474
|
+
totals: {
|
|
475
|
+
mode: 'async', // 异步统计总数
|
|
476
|
+
ttl: 300000 // 缓存 5 分钟
|
|
477
|
+
}
|
|
705
478
|
});
|
|
706
479
|
|
|
707
|
-
|
|
708
|
-
const user = await collection.findOneById('507f1f77bcf86cd799439011');
|
|
709
|
-
|
|
710
|
-
// 支持缓存和所有选项
|
|
711
|
-
const user = await collection.findOneById(userId, {
|
|
712
|
-
cache: 60000,
|
|
713
|
-
projection: { password: 0 }
|
|
714
|
-
});
|
|
480
|
+
console.log(`总计: ${result.totals.total}, 共 ${result.totals.totalPages} 页`);
|
|
715
481
|
```
|
|
716
482
|
|
|
717
|
-
|
|
483
|
+
### 8. 🛠️ 运维监控(开箱即用)
|
|
718
484
|
|
|
719
485
|
```javascript
|
|
720
|
-
//
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
|
|
486
|
+
// 🆕 慢查询日志持久化存储(v1.3+)
|
|
487
|
+
const msq = new MonSQLize({
|
|
488
|
+
type: 'mongodb',
|
|
489
|
+
config: { uri: 'mongodb://localhost:27017/mydb' },
|
|
490
|
+
slowQueryMs: 500,
|
|
491
|
+
slowQueryLog: true // ✅ 零配置启用,自动存储到 admin.slow_query_logs
|
|
724
492
|
});
|
|
725
|
-
// 返回: [{ _id, name, email }, { _id, name, email }, ...]
|
|
726
|
-
```
|
|
727
493
|
|
|
728
|
-
|
|
494
|
+
await msq.connect();
|
|
729
495
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
{ name: 'Alice', age: 30 } // 数据
|
|
496
|
+
// 查询慢查询日志(支持去重聚合)
|
|
497
|
+
const logs = await msq.getSlowQueryLogs(
|
|
498
|
+
{ collection: 'users' },
|
|
499
|
+
{ sort: { count: -1 }, limit: 10 } // 查询高频慢查询Top10
|
|
735
500
|
);
|
|
501
|
+
// [{ queryHash: 'abc123', count: 2400, avgTimeMs: 520, maxTimeMs: 1200, ... }]
|
|
736
502
|
|
|
737
|
-
//
|
|
738
|
-
//
|
|
739
|
-
// { email: 'alice@example.com' },
|
|
740
|
-
// { $set: { name: 'Alice', age: 30 } },
|
|
741
|
-
// { upsert: true }
|
|
742
|
-
// );
|
|
743
|
-
```
|
|
503
|
+
// 自动记录慢查询(原有功能)
|
|
504
|
+
// [WARN] Slow query { ns: 'mydb.users', duration: 1200ms, query: {...} }
|
|
744
505
|
|
|
745
|
-
|
|
506
|
+
// 健康检查
|
|
507
|
+
const health = await db.health();
|
|
508
|
+
// { status: 'ok', uptime: 3600, connections: 10 }
|
|
746
509
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
await collection.incrementOne({ _id: postId }, 'likes', 5);
|
|
751
|
-
|
|
752
|
-
// 递减
|
|
753
|
-
await collection.incrementOne({ _id: userId }, 'balance', -100);
|
|
754
|
-
|
|
755
|
-
// 支持缓存失效
|
|
756
|
-
await collection.incrementOne(
|
|
757
|
-
{ _id: userId },
|
|
758
|
-
'score',
|
|
759
|
-
10,
|
|
760
|
-
{ cache: 60000 }
|
|
761
|
-
);
|
|
510
|
+
// 性能指标
|
|
511
|
+
const stats = await db.getStats();
|
|
512
|
+
// { queries: 10000, cacheHits: 9000, hitRate: 0.9 }
|
|
762
513
|
```
|
|
763
514
|
|
|
764
|
-
|
|
515
|
+
### 9. 🔐 SSH隧道 - 安全连接内网数据库(v1.3+)
|
|
765
516
|
|
|
766
517
|
```javascript
|
|
767
|
-
//
|
|
768
|
-
const
|
|
769
|
-
|
|
770
|
-
{
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
518
|
+
// 场景:数据库位于防火墙后,无法直接访问
|
|
519
|
+
const db = new MonSQLize({
|
|
520
|
+
type: 'mongodb',
|
|
521
|
+
config: {
|
|
522
|
+
// SSH隧道配置
|
|
523
|
+
ssh: {
|
|
524
|
+
host: 'bastion.example.com', // SSH服务器(跳板机)
|
|
525
|
+
port: 22,
|
|
526
|
+
username: 'deploy',
|
|
527
|
+
password: 'your-password', // ✅ 支持密码认证
|
|
528
|
+
// 或使用私钥认证(推荐)
|
|
529
|
+
// privateKeyPath: '~/.ssh/id_rsa',
|
|
530
|
+
},
|
|
531
|
+
// MongoDB连接配置(内网地址,自动从URI解析remoteHost和remotePort)
|
|
532
|
+
uri: 'mongodb://user:pass@internal-mongo:27017/mydb'
|
|
775
533
|
}
|
|
776
|
-
);
|
|
777
|
-
|
|
778
|
-
console.log(`共 ${total} 条记录,当前返回 ${data.length} 条`);
|
|
779
|
-
// 输出: 共 1523 条记录,当前返回 20 条
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
📖 详细文档:
|
|
783
|
-
- [findOneById](./docs/find-one-by-id.md)
|
|
784
|
-
- [findByIds](./docs/find-by-ids.md)
|
|
785
|
-
- [upsertOne](./docs/upsert-one.md)
|
|
786
|
-
- [incrementOne](./docs/increment-one.md)
|
|
787
|
-
- [findAndCount](./docs/find-and-count.md)
|
|
788
|
-
|
|
789
|
-
---
|
|
790
|
-
|
|
791
|
-
### 高性能批量插入
|
|
792
|
-
|
|
793
|
-
**比原生驱动快 10-50 倍**:
|
|
794
|
-
|
|
795
|
-
```javascript
|
|
796
|
-
// 大批量插入(自动分批、并发、错误处理)
|
|
797
|
-
const result = await collection.insertBatch(largeArray, {
|
|
798
|
-
batchSize: 1000, // 每批1000条
|
|
799
|
-
ordered: false, // 无序插入(更快)
|
|
800
|
-
parallel: 5, // 5个并发批次
|
|
801
|
-
continueOnError: true, // 出错继续
|
|
802
|
-
retryOnError: true, // 失败重试
|
|
803
|
-
maxRetries: 3 // 最多重试3次
|
|
804
534
|
});
|
|
805
535
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
//
|
|
811
|
-
// - MongoDB 原生: 43,000ms
|
|
812
|
-
// - monSQLize: 1,700ms (25.3x 提升)
|
|
536
|
+
await db.connect(); // 自动建立SSH隧道
|
|
537
|
+
// 正常使用MongoDB,无需关心隧道细节
|
|
538
|
+
const users = db.collection('users');
|
|
539
|
+
const data = await users.findOne({});
|
|
540
|
+
await db.close(); // 自动关闭SSH隧道
|
|
813
541
|
```
|
|
814
542
|
|
|
815
|
-
|
|
816
|
-
- ✅
|
|
817
|
-
- ✅
|
|
818
|
-
- ✅
|
|
819
|
-
- ✅
|
|
820
|
-
- ✅ 进度回调,实时监控
|
|
821
|
-
|
|
822
|
-
📖 详细文档:[insertBatch](./docs/insertBatch.md)
|
|
823
|
-
|
|
824
|
-
---
|
|
825
|
-
|
|
826
|
-
### 链式调用 API
|
|
827
|
-
|
|
828
|
-
**完整支持 MongoDB 游标方法**:
|
|
829
|
-
|
|
830
|
-
```javascript
|
|
831
|
-
// 流畅的链式调用
|
|
832
|
-
const users = await collection
|
|
833
|
-
.find({ status: 'active' })
|
|
834
|
-
.sort({ createdAt: -1 }) // 排序
|
|
835
|
-
.skip(20) // 跳过
|
|
836
|
-
.limit(10) // 限制
|
|
837
|
-
.project({ name: 1, email: 1 }) // 投影
|
|
838
|
-
.hint({ status: 1 }) // 索引提示
|
|
839
|
-
.maxTimeMS(5000) // 超时控制
|
|
840
|
-
.comment('User list query') // 查询标识
|
|
841
|
-
.exec();
|
|
842
|
-
|
|
843
|
-
// 支持所有 MongoDB 游标方法
|
|
844
|
-
// sort, limit, skip, project, hint, collation,
|
|
845
|
-
// comment, maxTimeMS, batchSize, explain, stream
|
|
846
|
-
```
|
|
543
|
+
**特性**:
|
|
544
|
+
- ✅ 支持密码和私钥认证
|
|
545
|
+
- ✅ 自动管理隧道生命周期
|
|
546
|
+
- ✅ 完美跨平台(基于ssh2库)
|
|
547
|
+
- ✅ 开箱即用,零额外配置
|
|
847
548
|
|
|
848
|
-
📖
|
|
549
|
+
[📖 SSH隧道详细文档](./docs/ssh-tunnel.md)
|
|
849
550
|
|
|
850
551
|
---
|
|
851
552
|
|
|
852
|
-
###
|
|
853
|
-
|
|
854
|
-
**支持千万级数据的高性能分页**:
|
|
855
|
-
|
|
856
|
-
#### 1. 游标分页(推荐)
|
|
857
|
-
|
|
858
|
-
```javascript
|
|
859
|
-
// 页码分页(性能稳定,不受页数影响)
|
|
860
|
-
const result = await collection.findPage({
|
|
861
|
-
query: { status: 'active' },
|
|
862
|
-
page: 100, // 第100页依然快速
|
|
863
|
-
limit: 20,
|
|
864
|
-
sort: { createdAt: -1 },
|
|
865
|
-
totals: {
|
|
866
|
-
mode: 'async', // 异步统计总数
|
|
867
|
-
ttl: 300000 // 缓存 5 分钟
|
|
868
|
-
}
|
|
869
|
-
});
|
|
870
|
-
|
|
871
|
-
console.log(`第 ${result.pageInfo.currentPage} 页`);
|
|
872
|
-
console.log(`共 ${result.totals.total} 条,${result.totals.totalPages} 页`);
|
|
873
|
-
console.log(`数据:`, result.items);
|
|
874
|
-
```
|
|
553
|
+
### 10. 🎯 Model 层 - 像 ORM 一样使用(v1.0.3+)
|
|
875
554
|
|
|
876
|
-
|
|
555
|
+
monSQLize 提供了一个轻量级的 Model 层,让你可以像使用 ORM 一样定义数据模型,同时保持 MongoDB 的灵活性。
|
|
877
556
|
|
|
878
557
|
```javascript
|
|
879
|
-
|
|
880
|
-
let result = await collection.findPage({
|
|
881
|
-
query: { status: 'active' },
|
|
882
|
-
limit: 20,
|
|
883
|
-
sort: { createdAt: -1 }
|
|
884
|
-
});
|
|
885
|
-
|
|
886
|
-
// 下一页(使用游标)
|
|
887
|
-
result = await collection.findPage({
|
|
888
|
-
after: result.pageInfo.endCursor, // 使用上一页的结束游标
|
|
889
|
-
limit: 20,
|
|
890
|
-
sort: { createdAt: -1 }
|
|
891
|
-
});
|
|
558
|
+
const { Model } = require('monsqlize');
|
|
892
559
|
|
|
893
|
-
//
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
560
|
+
// 1. 定义 Model(集成 schema-dsl 验证)
|
|
561
|
+
Model.define('users', {
|
|
562
|
+
enums: {
|
|
563
|
+
role: 'admin|user|guest'
|
|
564
|
+
},
|
|
565
|
+
schema: function(dsl) {
|
|
566
|
+
return dsl({
|
|
567
|
+
username: 'string:3-32!',
|
|
568
|
+
email: 'email!',
|
|
569
|
+
role: this.enums.role.default('user'),
|
|
570
|
+
age: 'number:1-150'
|
|
571
|
+
});
|
|
572
|
+
},
|
|
573
|
+
options: {
|
|
574
|
+
timestamps: true, // 🆕 v1.0.3: 自动管理 createdAt/updatedAt
|
|
575
|
+
softDelete: true // 🆕 v1.0.3: 软删除(标记删除,支持恢复)
|
|
576
|
+
},
|
|
577
|
+
methods: (model) => ({
|
|
578
|
+
// 实例方法 - 注入到查询返回的文档对象
|
|
579
|
+
instance: {
|
|
580
|
+
isAdmin() {
|
|
581
|
+
return this.role === 'admin';
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
// 静态方法 - 挂载到 Model 实例
|
|
585
|
+
static: {
|
|
586
|
+
async findByEmail(email) {
|
|
587
|
+
return await model.findOne({ email });
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}),
|
|
591
|
+
hooks: (model) => ({
|
|
592
|
+
// 生命周期钩子
|
|
593
|
+
insert: {
|
|
594
|
+
before: (ctx, docs) => {
|
|
595
|
+
// 自动添加时间戳
|
|
596
|
+
return { ...docs, createdAt: new Date() };
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}),
|
|
600
|
+
indexes: [
|
|
601
|
+
{ key: { username: 1 }, unique: true },
|
|
602
|
+
{ key: { email: 1 }, unique: true }
|
|
603
|
+
]
|
|
898
604
|
});
|
|
899
|
-
```
|
|
900
605
|
|
|
901
|
-
|
|
606
|
+
// 2. 使用 Model
|
|
607
|
+
const db = new MonSQLize({ /* ... */ });
|
|
608
|
+
await db.connect();
|
|
902
609
|
|
|
903
|
-
|
|
904
|
-
|------|------|--------|---------|
|
|
905
|
-
| `none` | 最快 | - | 不需要总数 |
|
|
906
|
-
| `sync` | 快 | 100% | 小数据(< 10万)|
|
|
907
|
-
| `async` | 快 | 100% | 大数据(推荐)|
|
|
908
|
-
| `approx` | 最快 | ~95% | 超大数据,允许误差 |
|
|
610
|
+
const User = db.model('users');
|
|
909
611
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
612
|
+
// 自动 Schema 验证
|
|
613
|
+
const user = await User.insertOne({
|
|
614
|
+
username: 'john',
|
|
615
|
+
email: 'john@example.com',
|
|
616
|
+
age: 25
|
|
617
|
+
}); // ✅ 验证通过
|
|
916
618
|
|
|
917
|
-
|
|
619
|
+
// 使用实例方法
|
|
620
|
+
const admin = await User.findOne({ username: 'admin' });
|
|
621
|
+
console.log(admin.isAdmin()); // true
|
|
918
622
|
|
|
919
|
-
|
|
623
|
+
// 使用静态方法
|
|
624
|
+
const user = await User.findByEmail('john@example.com');
|
|
920
625
|
|
|
921
|
-
|
|
626
|
+
// 软删除(标记删除,可恢复)
|
|
627
|
+
await User.deleteOne({ _id: user._id });
|
|
922
628
|
|
|
923
|
-
|
|
629
|
+
// 查询(自动过滤已删除)
|
|
630
|
+
const users = await User.find({}); // 不包含已删除用户
|
|
924
631
|
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
const result = await collection.aggregate([
|
|
928
|
-
{ $match: { status: 'active' } },
|
|
929
|
-
{ $group: {
|
|
930
|
-
_id: '$city',
|
|
931
|
-
count: { $sum: 1 },
|
|
932
|
-
avgAge: { $avg: '$age' }
|
|
933
|
-
}},
|
|
934
|
-
{ $sort: { count: -1 } },
|
|
935
|
-
{ $limit: 10 }
|
|
936
|
-
], {
|
|
937
|
-
cache: 300000, // 缓存 5 分钟
|
|
938
|
-
maxTimeMS: 5000
|
|
939
|
-
});
|
|
632
|
+
// 查询包含已删除
|
|
633
|
+
const allUsers = await User.findWithDeleted({});
|
|
940
634
|
|
|
941
|
-
|
|
635
|
+
// 恢复已删除
|
|
636
|
+
await User.restore({ _id: user._id });
|
|
942
637
|
```
|
|
943
638
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
// 2. 数据转换
|
|
958
|
-
{ $project: {
|
|
959
|
-
year: { $year: '$date' },
|
|
960
|
-
month: { $month: '$date' },
|
|
961
|
-
revenue: 1,
|
|
962
|
-
category: 1
|
|
963
|
-
}},
|
|
964
|
-
|
|
965
|
-
// 3. 分组统计
|
|
966
|
-
{ $group: {
|
|
967
|
-
_id: { year: '$year', month: '$month', category: '$category' },
|
|
968
|
-
totalRevenue: { $sum: '$revenue' },
|
|
969
|
-
count: { $sum: 1 }
|
|
970
|
-
}},
|
|
971
|
-
|
|
972
|
-
// 4. 排序
|
|
973
|
-
{ $sort: { '_id.year': -1, '_id.month': -1, totalRevenue: -1 } }
|
|
974
|
-
], {
|
|
975
|
-
cache: 600000, // 缓存 10 分钟
|
|
976
|
-
allowDiskUse: true // 允许使用磁盘(大数据)
|
|
977
|
-
});
|
|
639
|
+
**特性**:
|
|
640
|
+
- ✅ Schema 验证(集成 schema-dsl)
|
|
641
|
+
- ✅ 自定义方法(instance + static)
|
|
642
|
+
- ✅ 生命周期钩子(before/after)
|
|
643
|
+
- ✅ 索引自动创建
|
|
644
|
+
- ✅ 自动时间戳(v1.0.3+)
|
|
645
|
+
- ✅ 软删除(v1.0.3+)
|
|
646
|
+
- ✅ 乐观锁版本控制(v1.0.3+)
|
|
647
|
+
- ✅ TypeScript 类型支持
|
|
648
|
+
|
|
649
|
+
**注意**:需要安装 `schema-dsl` 依赖:
|
|
650
|
+
```bash
|
|
651
|
+
npm install schema-dsl
|
|
978
652
|
```
|
|
979
653
|
|
|
980
|
-
📖
|
|
654
|
+
[📖 Model 层详细文档](./docs/model.md)
|
|
981
655
|
|
|
982
656
|
---
|
|
983
657
|
|
|
984
|
-
|
|
658
|
+
## 📊 性能测试报告
|
|
985
659
|
|
|
986
|
-
|
|
660
|
+
### 测试环境
|
|
987
661
|
|
|
988
|
-
|
|
662
|
+
- **CPU**: Intel i7-9700K
|
|
663
|
+
- **内存**: 16GB
|
|
664
|
+
- **数据库**: MongoDB 5.0
|
|
665
|
+
- **数据量**: 100 万条
|
|
989
666
|
|
|
990
|
-
|
|
991
|
-
// 监听集合的所有数据变更
|
|
992
|
-
const watcher = collection.watch();
|
|
993
|
-
|
|
994
|
-
watcher.on('change', (change) => {
|
|
995
|
-
console.log('数据变更:', change.operationType); // insert/update/delete/replace
|
|
996
|
-
console.log('文档ID:', change.documentKey._id);
|
|
997
|
-
console.log('完整文档:', change.fullDocument);
|
|
998
|
-
});
|
|
667
|
+
### 查询性能对比
|
|
999
668
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
669
|
+
| 场景 | 原生驱动 | monSQLize (缓存) | 提升倍数 |
|
|
670
|
+
|------|---------|------------------|---------|
|
|
671
|
+
| 热点查询 (findOne) | 10ms | 0.1ms | **100x** ⚡ |
|
|
672
|
+
| 列表查询 (find) | 50ms | 0.5ms | **100x** ⚡ |
|
|
673
|
+
| 复杂聚合 (aggregate) | 200ms | 2ms | **100x** ⚡ |
|
|
674
|
+
| 批量插入 (10万条) | 30s | 1.2s | **25x** ⚡ |
|
|
1005
675
|
|
|
1006
|
-
|
|
1007
|
-
// 只监听 insert 和 update 操作
|
|
1008
|
-
const watcher = collection.watch([
|
|
1009
|
-
{ $match: { operationType: { $in: ['insert', 'update'] } } }
|
|
1010
|
-
]);
|
|
676
|
+
### 缓存命中率
|
|
1011
677
|
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
```
|
|
678
|
+
- **电商场景**: 85% (商品/用户查询)
|
|
679
|
+
- **内容平台**: 75% (文章/评论查询)
|
|
680
|
+
- **社交应用**: 80% (个人资料/动态)
|
|
1016
681
|
|
|
1017
|
-
|
|
682
|
+
**结论**: 在真实业务场景中,缓存命中率通常在 **70~90%**,性能提升 **10~100 倍**。
|
|
1018
683
|
|
|
1019
|
-
|
|
1020
|
-
// 启用自动缓存失效(默认开启)
|
|
1021
|
-
const watcher = collection.watch([], {
|
|
1022
|
-
autoInvalidateCache: true // 数据变更时自动失效相关缓存
|
|
1023
|
-
});
|
|
684
|
+
---
|
|
1024
685
|
|
|
1025
|
-
|
|
1026
|
-
|
|
686
|
+
## 🎨 完整功能清单
|
|
687
|
+
|
|
688
|
+
<table>
|
|
689
|
+
<tr>
|
|
690
|
+
<td width="33%">
|
|
691
|
+
|
|
692
|
+
### 📦 MongoDB 原生功能
|
|
693
|
+
|
|
694
|
+
✅ **CRUD 操作**
|
|
695
|
+
- find / findOne
|
|
696
|
+
- insertOne / insertMany
|
|
697
|
+
- updateOne / updateMany
|
|
698
|
+
- deleteOne / deleteMany
|
|
699
|
+
- replaceOne
|
|
700
|
+
- findOneAndUpdate
|
|
701
|
+
- findOneAndReplace
|
|
702
|
+
- findOneAndDelete
|
|
703
|
+
|
|
704
|
+
✅ **聚合 & 查询**
|
|
705
|
+
- aggregate
|
|
706
|
+
- count / distinct
|
|
707
|
+
- watch (Change Streams)
|
|
708
|
+
- explain
|
|
709
|
+
|
|
710
|
+
✅ **索引管理**
|
|
711
|
+
- createIndex / createIndexes
|
|
712
|
+
- listIndexes
|
|
713
|
+
- dropIndex / dropIndexes
|
|
714
|
+
|
|
715
|
+
✅ **事务支持**
|
|
716
|
+
- withTransaction
|
|
717
|
+
- startTransaction
|
|
718
|
+
|
|
719
|
+
</td>
|
|
720
|
+
<td width="33%">
|
|
721
|
+
|
|
722
|
+
### 🚀 增强功能
|
|
723
|
+
|
|
724
|
+
✅ **智能缓存**
|
|
725
|
+
- TTL 过期策略
|
|
726
|
+
- LRU 淘汰策略
|
|
727
|
+
- 自动失效机制
|
|
728
|
+
- 并发去重
|
|
729
|
+
- 多层缓存 (内存+Redis)
|
|
730
|
+
|
|
731
|
+
✅ **便利方法**
|
|
732
|
+
- findOneById
|
|
733
|
+
- findByIds
|
|
734
|
+
- upsertOne
|
|
735
|
+
- incrementOne
|
|
736
|
+
- findAndCount
|
|
737
|
+
|
|
738
|
+
✅ **性能优化**
|
|
739
|
+
- insertBatch - 批量插入优化
|
|
740
|
+
- deleteBatch - 批量删除(流式+进度监控)
|
|
741
|
+
- updateBatch - 批量更新(流式+进度监控)
|
|
742
|
+
- 只读事务优化
|
|
743
|
+
- Count 队列控制
|
|
744
|
+
- 连接池管理
|
|
745
|
+
|
|
746
|
+
✅ **分布式支持**
|
|
747
|
+
- Redis 广播缓存失效
|
|
748
|
+
- 分布式锁
|
|
749
|
+
- 多实例一致性
|
|
750
|
+
|
|
751
|
+
</td>
|
|
752
|
+
<td width="33%">
|
|
753
|
+
|
|
754
|
+
### 🛠️ 企业级特性
|
|
755
|
+
|
|
756
|
+
✅ **运维监控**
|
|
757
|
+
- 慢查询日志(支持持久化存储)🆕
|
|
758
|
+
- 性能指标统计
|
|
759
|
+
- 健康检查
|
|
760
|
+
- 缓存命中率监控
|
|
761
|
+
|
|
762
|
+
✅ **深度分页**
|
|
763
|
+
- 游标分页
|
|
764
|
+
- 异步总数统计
|
|
765
|
+
- 书签管理
|
|
766
|
+
- 跳页优化
|
|
767
|
+
|
|
768
|
+
✅ **数据库管理**
|
|
769
|
+
- 跨库访问
|
|
770
|
+
- Schema 验证
|
|
771
|
+
- 集合管理
|
|
772
|
+
- 数据库命令
|
|
773
|
+
|
|
774
|
+
✅ **开发体验**
|
|
775
|
+
- TypeScript 支持
|
|
776
|
+
- 链式调用 API
|
|
777
|
+
- ESM/CommonJS 双模式
|
|
778
|
+
- 77% 测试覆盖率
|
|
779
|
+
|
|
780
|
+
</td>
|
|
781
|
+
</tr>
|
|
782
|
+
</table>
|
|
1027
783
|
|
|
1028
|
-
|
|
1029
|
-
await collection.updateOne({ _id: userId }, { $set: { status: 'inactive' } });
|
|
784
|
+
---
|
|
1030
785
|
|
|
1031
|
-
|
|
1032
|
-
// 4. 下次查询自动从数据库读取最新数据
|
|
1033
|
-
```
|
|
786
|
+
## 🆚 与 MongoDB 原生驱动对比
|
|
1034
787
|
|
|
1035
|
-
|
|
788
|
+
<table>
|
|
789
|
+
<tr>
|
|
790
|
+
<th width="25%">特性</th>
|
|
791
|
+
<th width="25%">MongoDB 原生</th>
|
|
792
|
+
<th width="50%"><strong>monSQLize</strong></th>
|
|
793
|
+
</tr>
|
|
794
|
+
<tr>
|
|
795
|
+
<td><strong>API 兼容性</strong></td>
|
|
796
|
+
<td>✅ 原生</td>
|
|
797
|
+
<td>✅ 100% 兼容原生,无需学习新 API</td>
|
|
798
|
+
</tr>
|
|
799
|
+
<tr>
|
|
800
|
+
<td><strong>智能缓存</strong></td>
|
|
801
|
+
<td>❌ 需要自己实现</td>
|
|
802
|
+
<td>✅ 内置 TTL/LRU,开箱即用,10~100倍提升</td>
|
|
803
|
+
</tr>
|
|
804
|
+
<tr>
|
|
805
|
+
<td><strong>性能</strong></td>
|
|
806
|
+
<td>⭐⭐⭐ 基准性能</td>
|
|
807
|
+
<td>⭐⭐⭐⭐⭐ 缓存命中时性能提升 10~100 倍</td>
|
|
808
|
+
</tr>
|
|
809
|
+
<tr>
|
|
810
|
+
<td><strong>事务支持</strong></td>
|
|
811
|
+
<td>⭐⭐ 需要手动管理</td>
|
|
812
|
+
<td>⭐⭐⭐⭐⭐ 自动管理生命周期,优化只读操作</td>
|
|
813
|
+
</tr>
|
|
814
|
+
<tr>
|
|
815
|
+
<td><strong>分布式部署</strong></td>
|
|
816
|
+
<td>❌ 缓存不一致</td>
|
|
817
|
+
<td>✅ Redis 广播自动同步,保证一致性</td>
|
|
818
|
+
</tr>
|
|
819
|
+
<tr>
|
|
820
|
+
<td><strong>便利方法</strong></td>
|
|
821
|
+
<td>❌ 需要自己封装</td>
|
|
822
|
+
<td>✅ findOneById、findByIds、upsertOne 等</td>
|
|
823
|
+
</tr>
|
|
824
|
+
<tr>
|
|
825
|
+
<td><strong>运维监控</strong></td>
|
|
826
|
+
<td>⚠️ 需要额外配置</td>
|
|
827
|
+
<td>✅ 慢查询日志、性能统计,开箱即用</td>
|
|
828
|
+
</tr>
|
|
829
|
+
<tr>
|
|
830
|
+
<td><strong>学习成本</strong></td>
|
|
831
|
+
<td>⭐⭐⭐ MongoDB 语法</td>
|
|
832
|
+
<td>⭐ 零学习成本,API 完全一致</td>
|
|
833
|
+
</tr>
|
|
834
|
+
<tr>
|
|
835
|
+
<td><strong>迁移成本</strong></td>
|
|
836
|
+
<td>-</td>
|
|
837
|
+
<td>⭐ 只需修改初始化代码,业务代码不变</td>
|
|
838
|
+
</tr>
|
|
839
|
+
</table>
|
|
840
|
+
|
|
841
|
+
### 📌 何时选择 monSQLize
|
|
842
|
+
|
|
843
|
+
✅ **适合场景**:
|
|
844
|
+
- 高并发读取场景(商品详情、用户信息)
|
|
845
|
+
- 需要缓存但不想自己实现
|
|
846
|
+
- 多实例部署需要缓存一致性
|
|
847
|
+
- 希望零学习成本提升性能
|
|
848
|
+
|
|
849
|
+
⚠️ **不适合场景**:
|
|
850
|
+
- 纯写入应用(缓存作用有限)
|
|
851
|
+
- 实时性要求极高(每次必查最新)
|
|
852
|
+
- 简单应用,流量不大(原生驱动足够)
|
|
1036
853
|
|
|
1037
|
-
|
|
1038
|
-
const watcher = collection.watch();
|
|
854
|
+
---
|
|
1039
855
|
|
|
1040
|
-
|
|
1041
|
-
watcher.on('error', (error) => {
|
|
1042
|
-
console.warn('持久性错误:', error.message);
|
|
1043
|
-
});
|
|
856
|
+
## 🚀 快速迁移指南
|
|
1044
857
|
|
|
1045
|
-
|
|
1046
|
-
watcher.on('reconnect', (info) => {
|
|
1047
|
-
console.log(`第 ${info.attempt} 次重连,延迟 ${info.delay}ms`);
|
|
1048
|
-
});
|
|
858
|
+
### 从 MongoDB 原生驱动迁移
|
|
1049
859
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
860
|
+
```javascript
|
|
861
|
+
// ❌ 原来的代码
|
|
862
|
+
const { MongoClient } = require('mongodb');
|
|
863
|
+
const client = await MongoClient.connect('mongodb://localhost:27017');
|
|
864
|
+
const db = client.db('mydb');
|
|
865
|
+
const users = db.collection('users');
|
|
1054
866
|
|
|
1055
|
-
//
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
867
|
+
// ✅ 迁移后的代码(只需改 3 行)
|
|
868
|
+
const MonSQLize = require('monsqlize'); // 1. 引入 monSQLize
|
|
869
|
+
const db = new MonSQLize({ // 2. 修改初始化
|
|
870
|
+
type: 'mongodb',
|
|
871
|
+
config: { uri: 'mongodb://localhost:27017/mydb' },
|
|
872
|
+
cache: { enabled: true } // 3. 启用缓存
|
|
1059
873
|
});
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
#### 5. 统计监控
|
|
874
|
+
await db.connect();
|
|
875
|
+
const users = db.collection('users');
|
|
1063
876
|
|
|
1064
|
-
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
// 获取运行统计
|
|
1068
|
-
const stats = watcher.getStats();
|
|
1069
|
-
console.log('总变更数:', stats.totalChanges);
|
|
1070
|
-
console.log('重连次数:', stats.reconnectAttempts);
|
|
1071
|
-
console.log('运行时长:', stats.uptime, 'ms');
|
|
1072
|
-
console.log('缓存失效次数:', stats.cacheInvalidations);
|
|
1073
|
-
console.log('活跃状态:', stats.isActive);
|
|
877
|
+
// 🎉 后续所有代码不需要改动,性能提升 10~100 倍!
|
|
878
|
+
const user = await users.findOne({ email }); // 完全一样的 API
|
|
1074
879
|
```
|
|
1075
880
|
|
|
1076
|
-
|
|
881
|
+
### 渐进式迁移
|
|
1077
882
|
|
|
1078
883
|
```javascript
|
|
1079
|
-
//
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
await db.close();
|
|
1083
|
-
process.exit(0);
|
|
1084
|
-
});
|
|
1085
|
-
```
|
|
884
|
+
// ✅ 可以混用原生驱动和 monSQLize
|
|
885
|
+
const nativeClient = await MongoClient.connect('...');
|
|
886
|
+
const monsqlize = new MonSQLize({ cache: { enabled: true } });
|
|
1086
887
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
- ✅ **断点续传**:resumeToken 自动管理,不丢失任何变更
|
|
1090
|
-
- ✅ **智能缓存失效**:数据变更时自动失效相关缓存
|
|
1091
|
-
- ✅ **跨实例同步**:分布式环境自动广播缓存失效
|
|
1092
|
-
- ✅ **完整事件系统**:change, error, reconnect, resume, close, fatal
|
|
1093
|
-
- ✅ **统计监控**:完整的运行统计和健康检查
|
|
1094
|
-
|
|
1095
|
-
**注意事项**:
|
|
1096
|
-
- ⚠️ **需要副本集**:Change Streams 需要 MongoDB 4.0+ 副本集或分片集群
|
|
1097
|
-
- ⚠️ **测试环境**:可使用 mongodb-memory-server 副本集模式
|
|
888
|
+
// 性能敏感的查询用 monSQLize(启用缓存)
|
|
889
|
+
const hotData = await monsqlize.collection('products').find({}, { cache: 60000 });
|
|
1098
890
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
const db = new MonSQLize({
|
|
1102
|
-
type: 'mongodb',
|
|
1103
|
-
databaseName: 'mydb',
|
|
1104
|
-
config: {
|
|
1105
|
-
useMemoryServer: true,
|
|
1106
|
-
memoryServerOptions: {
|
|
1107
|
-
instance: {
|
|
1108
|
-
replSet: 'rs0' // 启用副本集(支持 Change Streams)
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
});
|
|
891
|
+
// 简单查询用原生驱动
|
|
892
|
+
const coldData = await nativeClient.db('mydb').collection('logs').find({});
|
|
1113
893
|
```
|
|
1114
894
|
|
|
1115
|
-
📖 详细文档:[watch 方法完整指南](./docs/watch.md)
|
|
1116
|
-
|
|
1117
895
|
---
|
|
1118
896
|
|
|
1119
|
-
##
|
|
897
|
+
## 📖 完整文档
|
|
1120
898
|
|
|
1121
899
|
### 核心文档
|
|
1122
900
|
|
|
1123
901
|
- 📖 [完整 API 文档索引](./docs/INDEX.md)
|
|
1124
902
|
- 📖 [MongoDB 原生 vs monSQLize 对比](./docs/mongodb-native-vs-extensions.md)
|
|
1125
903
|
- 📖 [事务使用指南](./docs/transaction.md)
|
|
904
|
+
- 📖 [业务级分布式锁](./docs/business-lock.md) 🆕 v1.4.0
|
|
905
|
+
- 📖 [SSH隧道使用指南](./docs/ssh-tunnel.md) 🆕 v1.3+
|
|
1126
906
|
- 📖 [分布式部署指南](./docs/distributed-deployment.md)
|
|
1127
907
|
- 📖 [性能优化指南](./docs/transaction-optimizations.md)
|
|
1128
908
|
|
|
@@ -1131,130 +911,75 @@ const db = new MonSQLize({
|
|
|
1131
911
|
**CRUD 操作**:
|
|
1132
912
|
- [find](./docs/find.md) | [findOne](./docs/findOne.md) | [findPage](./docs/findPage.md)
|
|
1133
913
|
- [insertOne](./docs/insert-one.md) | [insertMany](./docs/insert-many.md) | [insertBatch](./docs/insertBatch.md)
|
|
1134
|
-
- [updateOne](./docs/update-one.md) | [updateMany](./docs/update-many.md) | [replaceOne](./docs/replace-one.md)
|
|
1135
|
-
- [deleteOne](./docs/delete-one.md) | [deleteMany](./docs/delete-many.md)
|
|
914
|
+
- [updateOne](./docs/update-one.md) | [updateMany](./docs/update-many.md) | [updateBatch](./docs/updateBatch.md) | [replaceOne](./docs/replace-one.md)
|
|
915
|
+
- [deleteOne](./docs/delete-one.md) | [deleteMany](./docs/delete-many.md) | [deleteBatch](./docs/deleteBatch.md)
|
|
916
|
+
|
|
917
|
+
**Model 层**:
|
|
918
|
+
- [Model API 文档](./docs/model.md) - Schema 验证、自定义方法、生命周期钩子
|
|
1136
919
|
|
|
1137
920
|
**便利方法**:
|
|
1138
921
|
- [findOneById](./docs/find-one-by-id.md) | [findByIds](./docs/find-by-ids.md)
|
|
1139
922
|
- [upsertOne](./docs/upsert-one.md) | [incrementOne](./docs/increment-one.md) | [findAndCount](./docs/find-and-count.md)
|
|
1140
923
|
|
|
1141
|
-
**Admin/Management**:
|
|
1142
|
-
- [运维监控](./docs/admin.md) | [数据库操作](./docs/database-ops.md)
|
|
1143
|
-
- [Schema 验证](./docs/validation.md) | [集合管理](./docs/collection-mgmt.md)
|
|
1144
|
-
|
|
1145
924
|
**其他功能**:
|
|
1146
|
-
- [索引管理](./docs/
|
|
925
|
+
- [索引管理](./docs/create-index.md) | [聚合查询](./docs/aggregate.md)
|
|
1147
926
|
- [缓存系统](./docs/cache.md) | [链式调用](./docs/chaining-api.md)
|
|
1148
927
|
|
|
1149
928
|
### 示例代码
|
|
1150
929
|
|
|
1151
|
-
- 📁 [完整示例代码目录](./examples/)
|
|
1152
|
-
- 50+ 可运行示例,涵盖所有功能场景
|
|
930
|
+
- 📁 [完整示例代码目录](./examples/) - 50+ 可运行示例
|
|
1153
931
|
|
|
1154
932
|
---
|
|
1155
933
|
|
|
1156
|
-
##
|
|
1157
|
-
|
|
1158
|
-
运行性能基准测试:
|
|
934
|
+
## 🌍 兼容性
|
|
1159
935
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
936
|
+
| 环境 | 支持版本 |
|
|
937
|
+
|------|---------|
|
|
938
|
+
| **Node.js** | 16.x, 18.x, 20.x, 21.x |
|
|
939
|
+
| **MongoDB** | 4.4+, 5.x, 6.x, 7.x |
|
|
940
|
+
| **MongoDB Driver** | 4.x, 5.x, 6.x, 7.x |
|
|
941
|
+
| **模块系统** | CommonJS, ESM |
|
|
1163
942
|
|
|
1164
|
-
|
|
1165
|
-
- [批量插入基准](./test/benchmark/insertBatch-benchmark.js)
|
|
1166
|
-
- [事务性能基准](./test/performance/transaction-benchmark.js)
|
|
943
|
+
[查看完整兼容性矩阵](./docs/COMPATIBILITY.md)
|
|
1167
944
|
|
|
1168
945
|
---
|
|
1169
946
|
|
|
1170
|
-
##
|
|
1171
|
-
|
|
1172
|
-
### ✅ 完整兼容性测试
|
|
1173
|
-
|
|
1174
|
-
monSQLize 已经过全面的多版本兼容性测试,确保在不同环境下稳定运行。
|
|
1175
|
-
|
|
1176
|
-
#### Node.js 版本
|
|
1177
|
-
|
|
1178
|
-
| 版本 | 支持状态 | 测试状态 |
|
|
1179
|
-
|------|---------|---------|
|
|
1180
|
-
| 14.x | ✅ 支持 | ✅ 已测试 |
|
|
1181
|
-
| 16.x | ✅ 支持 | ✅ 已测试 |
|
|
1182
|
-
| 18.x | ✅ 完全支持 | ✅ 已测试(推荐)|
|
|
1183
|
-
| 20.x | ✅ 完全支持 | ✅ 已测试(推荐)|
|
|
1184
|
-
| 22.x | ✅ 支持 | ✅ 已测试 |
|
|
1185
|
-
|
|
1186
|
-
#### MongoDB 驱动版本
|
|
1187
|
-
|
|
1188
|
-
| 版本 | 支持状态 | 测试状态 | 测试日期 | 说明 |
|
|
1189
|
-
|------|---------|---------|---------|------|
|
|
1190
|
-
| 4.x (4.17.2) | ✅ 完全支持 | ✅ 已测试 | 2025-01-02 | 自动适配 API 差异 |
|
|
1191
|
-
| 5.x (5.9.2) | ✅ 完全支持 | ✅ 已测试 | 2025-01-02 | 自动统一返回值 |
|
|
1192
|
-
| 6.x (6.17.0) | ✅ 完全支持 | ✅ 已测试 | 2025-01-02 | 推荐使用 |
|
|
1193
|
-
| 7.x (7.0.0) | ✅ 完全支持 | ✅ 已测试 | 2025-01-02 | 最新版本 |
|
|
1194
|
-
|
|
1195
|
-
**✅ 测试验证** (2025-01-02):
|
|
1196
|
-
- Driver 7.0.0: ✅ 通过(103.49s,100% 通过率)
|
|
1197
|
-
- 测试套件: 30/30 通过
|
|
1198
|
-
- 测试用例: 102 个全部通过
|
|
1199
|
-
|
|
1200
|
-
**✅ 自动处理的差异**:
|
|
1201
|
-
- ✅ **findOneAnd* 返回值统一**:Driver 4.x/5.x/6.x 的返回值格式完全统一
|
|
1202
|
-
- ✅ **连接选项自动适配**:自动处理 `useNewUrlParser` 等选项差异
|
|
1203
|
-
- ✅ **版本特性自动检测**:自动识别 Driver 版本并启用相应功能
|
|
1204
|
-
|
|
1205
|
-
**用户无需关心版本差异**:
|
|
1206
|
-
```javascript
|
|
1207
|
-
// 所有 Driver 版本代码完全相同
|
|
1208
|
-
const user = await collection.findOneAndUpdate(
|
|
1209
|
-
{ name: 'Alice' },
|
|
1210
|
-
{ $set: { age: 31 } }
|
|
1211
|
-
);
|
|
1212
|
-
// ✅ 统一返回:{ _id: ..., name: "Alice", age: 31 }
|
|
1213
|
-
```
|
|
1214
|
-
|
|
1215
|
-
#### MongoDB Server 版本
|
|
1216
|
-
|
|
1217
|
-
| 版本 | 支持状态 | 测试状态 | 特性限制 |
|
|
1218
|
-
|------|---------|---------|---------|
|
|
1219
|
-
| 4.4 | ✅ 支持 | ✅ 已测试 | 基础功能 |
|
|
1220
|
-
| 5.0 | ✅ 完全支持 | ✅ 已测试 | 时间序列集合 |
|
|
1221
|
-
| 6.0 | ✅ 完全支持 | ✅ 已测试(推荐)| 加密字段 |
|
|
1222
|
-
| 7.0 | ✅ 完全支持 | ✅ 已测试 | 最新特性 |
|
|
1223
|
-
|
|
1224
|
-
**智能特性探测**:
|
|
1225
|
-
- ✅ 自动检测 Server 版本
|
|
1226
|
-
- ✅ 特性支持探测(事务、索引、聚合)
|
|
1227
|
-
- ✅ 条件性测试(自动跳过不支持的特性)
|
|
1228
|
-
|
|
1229
|
-
### 📚 兼容性文档
|
|
1230
|
-
|
|
1231
|
-
- 📖 [**完整兼容性矩阵**](./docs/COMPATIBILITY.md) - 所有版本的详细支持说明
|
|
1232
|
-
- 📖 [**兼容性测试指南**](./docs/COMPATIBILITY-TESTING-GUIDE.md) - 如何运行兼容性测试
|
|
1233
|
-
- 📖 [MongoDB 驱动差异详解](./docs/mongodb-driver-compatibility.md) - Driver 5.x vs 6.x 差异
|
|
947
|
+
## 🗺️ 产品路线图
|
|
1234
948
|
|
|
1235
|
-
###
|
|
949
|
+
### ✅ v1.4 (当前版本)
|
|
1236
950
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
951
|
+
- ✅ 业务级分布式锁
|
|
952
|
+
- ✅ 智能缓存系统
|
|
953
|
+
- ✅ 事务优化
|
|
954
|
+
- ✅ 便利方法
|
|
955
|
+
- ✅ 分布式支持
|
|
956
|
+
- ✅ Model 层(v1.0.3)- Schema 验证、自定义方法、生命周期钩子
|
|
1240
957
|
|
|
1241
|
-
|
|
1242
|
-
npm run test:compatibility:node
|
|
958
|
+
### 🚧 v1.5 (计划中)
|
|
1243
959
|
|
|
1244
|
-
|
|
1245
|
-
|
|
960
|
+
- 🔄 查询分析器
|
|
961
|
+
- 🔄 自动索引建议
|
|
962
|
+
- 🔄 数据迁移工具
|
|
963
|
+
- 🔄 GraphQL 支持
|
|
964
|
+
- 🔄 Model 关系(relations)完善
|
|
1246
965
|
|
|
1247
|
-
|
|
1248
|
-
npm run test:compatibility:server
|
|
1249
|
-
```
|
|
966
|
+
### 🔮 v2.0 (未来)
|
|
1250
967
|
|
|
1251
|
-
|
|
968
|
+
- 🔮 统一 API 支持 MySQL
|
|
969
|
+
- 🔮 统一 API 支持 PostgreSQL
|
|
970
|
+
- 🔮 完整 ORM 功能
|
|
971
|
+
- 🔮 数据同步中间件
|
|
1252
972
|
|
|
1253
973
|
---
|
|
1254
974
|
|
|
1255
975
|
## 🤝 贡献指南
|
|
1256
976
|
|
|
1257
|
-
|
|
977
|
+
我们欢迎所有形式的贡献!
|
|
978
|
+
|
|
979
|
+
- 🐛 [提交 Bug](https://github.com/vextjs/monSQLize/issues)
|
|
980
|
+
- 💡 [提出新功能](https://github.com/vextjs/monSQLize/issues)
|
|
981
|
+
- 📖 [改进文档](https://github.com/vextjs/monSQLize/pulls)
|
|
982
|
+
- 💻 [提交代码](https://github.com/vextjs/monSQLize/pulls)
|
|
1258
983
|
|
|
1259
984
|
### 开发
|
|
1260
985
|
|
|
@@ -1269,236 +994,48 @@ npm install
|
|
|
1269
994
|
# 运行测试
|
|
1270
995
|
npm test
|
|
1271
996
|
|
|
1272
|
-
#
|
|
1273
|
-
npm run
|
|
1274
|
-
|
|
1275
|
-
# 检查测试覆盖率
|
|
1276
|
-
npm run coverage
|
|
1277
|
-
|
|
1278
|
-
# 运行 Lint 检查
|
|
1279
|
-
npm run lint
|
|
1280
|
-
```
|
|
1281
|
-
|
|
1282
|
-
---
|
|
1283
|
-
|
|
1284
|
-
## 🗺️ 产品路线图
|
|
1285
|
-
|
|
1286
|
-
### v1.x - MongoDB 专注版 ✅ (当前)
|
|
1287
|
-
|
|
1288
|
-
**已完成功能**:
|
|
1289
|
-
- ✅ **MongoDB 完整支持** (Driver 4.x - 7.x)
|
|
1290
|
-
- 16 个 CRUD 方法
|
|
1291
|
-
- 5 个索引管理方法
|
|
1292
|
-
- 8 个事务方法
|
|
1293
|
-
- 18 个 Admin/Management 方法
|
|
1294
|
-
|
|
1295
|
-
- ✅ **智能缓存系统**
|
|
1296
|
-
- TTL(时间过期)
|
|
1297
|
-
- LRU(最近最少使用淘汰)
|
|
1298
|
-
- 自动缓存失效
|
|
1299
|
-
- Redis 分布式广播
|
|
1300
|
-
|
|
1301
|
-
- ✅ **性能优化**
|
|
1302
|
-
- 10-100x 查询性能提升
|
|
1303
|
-
- 25x 批量插入性能
|
|
1304
|
-
- -30% 事务 DB 访问
|
|
1305
|
-
- 16x 并发性能(文档级锁)
|
|
1306
|
-
|
|
1307
|
-
- ✅ **企业级特性**
|
|
1308
|
-
- 分布式部署(Redis Pub/Sub)
|
|
1309
|
-
- 慢查询日志
|
|
1310
|
-
- 性能监控
|
|
1311
|
-
- 健康检查
|
|
1312
|
-
|
|
1313
|
-
- ✅ **便利方法**
|
|
1314
|
-
- `findOneById` / `findByIds`
|
|
1315
|
-
- `upsertOne` / `incrementOne`
|
|
1316
|
-
- `findAndCount`
|
|
1317
|
-
|
|
1318
|
-
**测试和文档**:
|
|
1319
|
-
- ✅ 77%+ 测试覆盖率
|
|
1320
|
-
- ✅ 100% API 文档
|
|
1321
|
-
- ✅ 50+ 可运行示例
|
|
1322
|
-
- ✅ 兼容性测试(Driver 4.x-7.x, Node.js 14-22)
|
|
1323
|
-
|
|
1324
|
-
---
|
|
1325
|
-
|
|
1326
|
-
### v2.x - 多数据库统一 API 📋 (规划中)
|
|
1327
|
-
|
|
1328
|
-
**核心目标**:使用统一的 MongoDB 风格 API 操作多种数据库
|
|
1329
|
-
|
|
1330
|
-
#### MySQL 支持
|
|
1331
|
-
```javascript
|
|
1332
|
-
// 统一的 MongoDB 风格 API
|
|
1333
|
-
const db = new MonSQLize({
|
|
1334
|
-
type: 'mysql', // ← 新增支持
|
|
1335
|
-
config: {
|
|
1336
|
-
host: 'localhost',
|
|
1337
|
-
user: 'root',
|
|
1338
|
-
database: 'mydb'
|
|
1339
|
-
}
|
|
1340
|
-
});
|
|
1341
|
-
|
|
1342
|
-
await db.connect();
|
|
1343
|
-
const users = db.collection('users');
|
|
1344
|
-
|
|
1345
|
-
// 使用 MongoDB 语法查询 MySQL
|
|
1346
|
-
await users.find({
|
|
1347
|
-
status: 'active',
|
|
1348
|
-
age: { $gte: 18 }
|
|
1349
|
-
});
|
|
1350
|
-
// ↓ 自动转换为 SQL
|
|
1351
|
-
// SELECT * FROM users WHERE status = 'active' AND age >= 18
|
|
1352
|
-
|
|
1353
|
-
// MongoDB 风格的更新
|
|
1354
|
-
await users.updateOne(
|
|
1355
|
-
{ _id: 1 },
|
|
1356
|
-
{ $set: { name: 'Alice' }, $inc: { loginCount: 1 } }
|
|
1357
|
-
);
|
|
1358
|
-
// ↓ 自动转换为 SQL
|
|
1359
|
-
// UPDATE users SET name = 'Alice', loginCount = loginCount + 1 WHERE id = 1
|
|
1360
|
-
|
|
1361
|
-
// 聚合查询
|
|
1362
|
-
await users.aggregate([
|
|
1363
|
-
{ $match: { status: 'active' } },
|
|
1364
|
-
{ $group: { _id: '$role', count: { $sum: 1 } } }
|
|
1365
|
-
]);
|
|
1366
|
-
// ↓ 自动转换为 SQL
|
|
1367
|
-
// SELECT role, COUNT(*) as count FROM users WHERE status = 'active' GROUP BY role
|
|
1368
|
-
```
|
|
1369
|
-
|
|
1370
|
-
#### PostgreSQL 支持
|
|
1371
|
-
```javascript
|
|
1372
|
-
const db = new MonSQLize({
|
|
1373
|
-
type: 'postgres', // ← 新增支持
|
|
1374
|
-
config: {
|
|
1375
|
-
host: 'localhost',
|
|
1376
|
-
database: 'mydb'
|
|
1377
|
-
}
|
|
1378
|
-
});
|
|
1379
|
-
|
|
1380
|
-
// JSONB 字段自动映射
|
|
1381
|
-
await users.find({
|
|
1382
|
-
'metadata.tags': { $in: ['tech', 'news'] }
|
|
1383
|
-
});
|
|
1384
|
-
// ↓ 利用 PostgreSQL 的 JSONB 特性
|
|
1385
|
-
// SELECT * FROM users WHERE metadata->'tags' ?| ARRAY['tech', 'news']
|
|
1386
|
-
|
|
1387
|
-
// 数组操作
|
|
1388
|
-
await users.updateOne(
|
|
1389
|
-
{ _id: 1 },
|
|
1390
|
-
{ $push: { 'metadata.tags': 'featured' } }
|
|
1391
|
-
);
|
|
1392
|
-
// ↓ PostgreSQL 数组操作
|
|
1393
|
-
// UPDATE users SET metadata = jsonb_set(metadata, '{tags}', ...) WHERE id = 1
|
|
997
|
+
# 运行基准测试
|
|
998
|
+
npm run benchmark
|
|
1394
999
|
```
|
|
1395
1000
|
|
|
1396
|
-
**技术路线**:
|
|
1397
|
-
1. **定义统一查询 AST**(抽象语法树)
|
|
1398
|
-
- MongoDB 查询 → AST → SQL 转换
|
|
1399
|
-
- 支持 90% 常用 MongoDB 操作符
|
|
1400
|
-
|
|
1401
|
-
2. **SQL 方言适配器**
|
|
1402
|
-
- MySQL: `LIMIT`, `AUTO_INCREMENT`
|
|
1403
|
-
- PostgreSQL: `JSONB`, `RETURNING`
|
|
1404
|
-
- SQL Server: `TOP`, `IDENTITY`
|
|
1405
|
-
|
|
1406
|
-
3. **保持核心功能**
|
|
1407
|
-
- 智能缓存(跨数据库)
|
|
1408
|
-
- 事务管理(适配各数据库)
|
|
1409
|
-
- 性能监控
|
|
1410
|
-
|
|
1411
|
-
4. **操作符映射表**
|
|
1412
|
-
|
|
1413
|
-
| MongoDB 操作符 | MySQL | PostgreSQL | SQL Server |
|
|
1414
|
-
|---------------|-------|------------|------------|
|
|
1415
|
-
| `$eq` (等于) | `=` | `=` | `=` |
|
|
1416
|
-
| `$ne` (不等于) | `!=` | `<>` | `<>` |
|
|
1417
|
-
| `$gt` (大于) | `>` | `>` | `>` |
|
|
1418
|
-
| `$gte` (大于等于) | `>=` | `>=` | `>=` |
|
|
1419
|
-
| `$lt` (小于) | `<` | `<` | `<` |
|
|
1420
|
-
| `$lte` (小于等于) | `<=` | `<=` | `<=` |
|
|
1421
|
-
| `$in` (在数组中) | `IN (...)` | `IN (...)` | `IN (...)` |
|
|
1422
|
-
| `$nin` (不在数组中) | `NOT IN (...)` | `NOT IN (...)` | `NOT IN (...)` |
|
|
1423
|
-
| `$regex` (正则匹配) | `REGEXP` | `~` | `LIKE` |
|
|
1424
|
-
| `$exists` (字段存在) | `IS NOT NULL` | `IS NOT NULL` | `IS NOT NULL` |
|
|
1425
|
-
| `$set` (设置字段) | `SET col = val` | `SET col = val` | `SET col = val` |
|
|
1426
|
-
| `$inc` (递增) | `SET col = col + n` | `SET col = col + n` | `SET col = col + n` |
|
|
1427
|
-
| `$unset` (删除字段) | `SET col = NULL` | `SET col = NULL` | `SET col = NULL` |
|
|
1428
|
-
| `$push` (数组添加) | `JSON_ARRAY_APPEND()` | `array_append()` | `JSON_MODIFY()` |
|
|
1429
|
-
| `$pull` (数组删除) | `JSON_REMOVE()` | `array_remove()` | `JSON_MODIFY()` |
|
|
1430
|
-
| `$addToSet` (集合添加) | `JSON_ARRAY_APPEND()` | `array_append()` | `JSON_MODIFY()` |
|
|
1431
|
-
|
|
1432
|
-
**限制说明**:
|
|
1433
|
-
- ⚠️ 某些 MongoDB 特性无法完美映射(如 `$lookup` 跨集合)
|
|
1434
|
-
- ⚠️ 性能可能不如原生 SQL(增加了转换层)
|
|
1435
|
-
- ✅ 90% 常用场景可以无缝支持
|
|
1436
|
-
|
|
1437
|
-
**预计时间**:2025 Q3-Q4
|
|
1438
|
-
|
|
1439
1001
|
---
|
|
1440
1002
|
|
|
1441
|
-
|
|
1003
|
+
## 📄 许可证
|
|
1442
1004
|
|
|
1443
|
-
|
|
1444
|
-
- 🔮 **SQL Server 支持**
|
|
1445
|
-
- 🔮 **Redis 作为主数据库**(文档存储)
|
|
1446
|
-
- 🔮 **其他 NoSQL**(Cassandra, DynamoDB)
|
|
1447
|
-
- 🔮 **混合查询**(跨数据库 Join)
|
|
1448
|
-
- 🔮 **数据库迁移工具**(MongoDB ↔ MySQL)
|
|
1449
|
-
- 🔮 **查询优化器**(自动选择最优执行计划)
|
|
1005
|
+
[MIT License](./LICENSE)
|
|
1450
1006
|
|
|
1451
1007
|
---
|
|
1452
1008
|
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
如果你对多数据库支持感兴趣,欢迎参与:
|
|
1456
|
-
|
|
1457
|
-
**贡献方式**:
|
|
1458
|
-
- 💡 **提出设计建议** - [GitHub Issues](https://github.com/vextjs/monSQLize/issues)
|
|
1459
|
-
- 🔧 **贡献代码** - [Pull Requests](https://github.com/vextjs/monSQLize/pulls)
|
|
1460
|
-
- 📖 **完善文档** - 帮助改进文档
|
|
1461
|
-
- 🧪 **提供测试用例** - 增加测试覆盖率
|
|
1462
|
-
- 🌍 **国际化** - 翻译文档到其他语言
|
|
1463
|
-
|
|
1464
|
-
**技术栈**:
|
|
1465
|
-
- Node.js 14+
|
|
1466
|
-
- MongoDB Driver
|
|
1467
|
-
- (未来) MySQL/PostgreSQL Drivers
|
|
1468
|
-
- TypeScript (类型定义)
|
|
1009
|
+
## 💬 社区与支持
|
|
1469
1010
|
|
|
1470
|
-
|
|
1471
|
-
-
|
|
1472
|
-
-
|
|
1473
|
-
-
|
|
1011
|
+
- 📧 **Email**: support@monsqlize.dev
|
|
1012
|
+
- 💬 **Issues**: [GitHub Issues](https://github.com/vextjs/monSQLize/issues)
|
|
1013
|
+
- 📖 **文档**: [完整文档](./docs/INDEX.md)
|
|
1014
|
+
- 🌟 **Star**: 如果觉得有用,请给我们一个 Star ⭐
|
|
1474
1015
|
|
|
1475
1016
|
---
|
|
1476
1017
|
|
|
1477
|
-
##
|
|
1478
|
-
|
|
1479
|
-
[MIT License](./LICENSE)
|
|
1018
|
+
## 🎉 快速链接
|
|
1480
1019
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
## 🌟 Star History
|
|
1020
|
+
<div align="center">
|
|
1484
1021
|
|
|
1485
|
-
|
|
1022
|
+
**[🚀 快速开始](#-5分钟快速开始)** ·
|
|
1023
|
+
**[📚 完整文档](./docs/INDEX.md)** ·
|
|
1024
|
+
**[💻 示例代码](./examples/)** ·
|
|
1025
|
+
**[🐛 报告问题](https://github.com/vextjs/monSQLize/issues)** ·
|
|
1026
|
+
**[⭐ Star 项目](https://github.com/vextjs/monSQLize)**
|
|
1486
1027
|
|
|
1487
1028
|
---
|
|
1488
1029
|
|
|
1489
|
-
|
|
1030
|
+
### 让 MongoDB 快 10~100 倍,从现在开始 🚀
|
|
1490
1031
|
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1032
|
+
```bash
|
|
1033
|
+
npm install monsqlize
|
|
1034
|
+
```
|
|
1494
1035
|
|
|
1495
1036
|
---
|
|
1496
1037
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
**由 ❤️ 用心打造**
|
|
1500
|
-
|
|
1501
|
-
[GitHub](https://github.com/vextjs/monSQLize) | [npm](https://www.npmjs.com/package/monsqlize) | [文档](./docs/INDEX.md) | [示例](./examples/)
|
|
1038
|
+
Made with ❤️ by monSQLize Team
|
|
1502
1039
|
|
|
1503
1040
|
</div>
|
|
1504
1041
|
|