monsqlize 1.3.0 → 2.0.0

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.
Files changed (172) hide show
  1. package/CHANGELOG.md +56 -60
  2. package/LICENSE +201 -21
  3. package/README.md +537 -1828
  4. package/changelogs/README.md +160 -0
  5. package/changelogs/v2.0.0.md +222 -0
  6. package/dist/cjs/index.cjs +10600 -0
  7. package/dist/cjs/mongodb/common/transaction-aware.cjs +10 -0
  8. package/dist/cjs/transaction/CacheLockManager.cjs +100 -0
  9. package/dist/cjs/transaction/Transaction.cjs +158 -0
  10. package/dist/cjs/transaction/TransactionManager.cjs +298 -0
  11. package/dist/esm/index.mjs +10650 -0
  12. package/dist/types/base.d.ts +81 -0
  13. package/dist/types/collection.d.ts +1031 -0
  14. package/dist/types/expression.d.ts +115 -0
  15. package/dist/types/index.d.ts +23 -0
  16. package/dist/types/lock.d.ts +74 -0
  17. package/dist/types/model.d.ts +526 -0
  18. package/dist/types/mongodb.d.ts +49 -0
  19. package/dist/types/monsqlize.d.ts +491 -0
  20. package/dist/types/pool.d.ts +84 -0
  21. package/dist/types/runtime.d.ts +362 -0
  22. package/dist/types/saga.d.ts +143 -0
  23. package/dist/types/slow-query-log.d.ts +126 -0
  24. package/dist/types/sync.d.ts +103 -0
  25. package/dist/types/transaction.d.ts +132 -0
  26. package/package.json +67 -69
  27. package/index.d.ts +0 -206
  28. package/index.mjs +0 -52
  29. package/lib/cache-invalidation.js +0 -279
  30. package/lib/cache.js +0 -530
  31. package/lib/common/cursor.js +0 -59
  32. package/lib/common/docs-urls.js +0 -73
  33. package/lib/common/index-options.js +0 -223
  34. package/lib/common/log.js +0 -61
  35. package/lib/common/namespace.js +0 -22
  36. package/lib/common/normalize.js +0 -34
  37. package/lib/common/page-result.js +0 -43
  38. package/lib/common/runner.js +0 -57
  39. package/lib/common/server-features.js +0 -232
  40. package/lib/common/shape-builders.js +0 -27
  41. package/lib/common/validation.js +0 -113
  42. package/lib/connect.js +0 -99
  43. package/lib/constants.js +0 -55
  44. package/lib/count-queue.js +0 -188
  45. package/lib/distributed-cache-invalidator.js +0 -260
  46. package/lib/errors.js +0 -168
  47. package/lib/expression/cache/ExpressionCache.js +0 -114
  48. package/lib/expression/compiler/ExpressionCompiler.js +0 -1090
  49. package/lib/expression/compiler/ExpressionCompilerExtensions.js +0 -531
  50. package/lib/expression/detector.js +0 -84
  51. package/lib/expression/factory.js +0 -29
  52. package/lib/expression/index.js +0 -19
  53. package/lib/function-cache.js +0 -533
  54. package/lib/index.js +0 -1251
  55. package/lib/infrastructure/ConnectionPoolManager.js +0 -464
  56. package/lib/infrastructure/HealthChecker.js +0 -281
  57. package/lib/infrastructure/PoolConfig.js +0 -199
  58. package/lib/infrastructure/PoolSelector.js +0 -225
  59. package/lib/infrastructure/PoolStats.js +0 -244
  60. package/lib/infrastructure/ssh-tunnel-ssh2.js +0 -212
  61. package/lib/infrastructure/ssh-tunnel.js +0 -41
  62. package/lib/infrastructure/uri-parser.js +0 -36
  63. package/lib/lock/Lock.js +0 -67
  64. package/lib/lock/errors.js +0 -28
  65. package/lib/lock/index.js +0 -13
  66. package/lib/logger.js +0 -225
  67. package/lib/model/examples/test.js +0 -311
  68. package/lib/model/features/defaults.js +0 -161
  69. package/lib/model/features/populate.js +0 -568
  70. package/lib/model/features/relations.js +0 -120
  71. package/lib/model/features/soft-delete.js +0 -349
  72. package/lib/model/features/version.js +0 -157
  73. package/lib/model/features/virtuals.js +0 -219
  74. package/lib/model/index.js +0 -1265
  75. package/lib/mongodb/common/accessor-helpers.js +0 -59
  76. package/lib/mongodb/common/agg-pipeline.js +0 -36
  77. package/lib/mongodb/common/aggregation-validator.js +0 -127
  78. package/lib/mongodb/common/iid.js +0 -28
  79. package/lib/mongodb/common/lexicographic-expr.js +0 -53
  80. package/lib/mongodb/common/shape.js +0 -32
  81. package/lib/mongodb/common/sort.js +0 -39
  82. package/lib/mongodb/common/transaction-aware.js +0 -25
  83. package/lib/mongodb/connect.js +0 -234
  84. package/lib/mongodb/index.js +0 -639
  85. package/lib/mongodb/management/admin-ops.js +0 -200
  86. package/lib/mongodb/management/bookmark-ops.js +0 -167
  87. package/lib/mongodb/management/cache-ops.js +0 -50
  88. package/lib/mongodb/management/collection-ops.js +0 -387
  89. package/lib/mongodb/management/database-ops.js +0 -202
  90. package/lib/mongodb/management/index-ops.js +0 -475
  91. package/lib/mongodb/management/index.js +0 -17
  92. package/lib/mongodb/management/namespace.js +0 -31
  93. package/lib/mongodb/management/validation-ops.js +0 -268
  94. package/lib/mongodb/queries/aggregate.js +0 -172
  95. package/lib/mongodb/queries/chain.js +0 -631
  96. package/lib/mongodb/queries/count.js +0 -99
  97. package/lib/mongodb/queries/distinct.js +0 -78
  98. package/lib/mongodb/queries/find-and-count.js +0 -193
  99. package/lib/mongodb/queries/find-by-ids.js +0 -236
  100. package/lib/mongodb/queries/find-one-by-id.js +0 -171
  101. package/lib/mongodb/queries/find-one.js +0 -71
  102. package/lib/mongodb/queries/find-page.js +0 -618
  103. package/lib/mongodb/queries/find.js +0 -171
  104. package/lib/mongodb/queries/index.js +0 -51
  105. package/lib/mongodb/queries/watch.js +0 -538
  106. package/lib/mongodb/writes/common/batch-retry.js +0 -65
  107. package/lib/mongodb/writes/delete-batch.js +0 -323
  108. package/lib/mongodb/writes/delete-many.js +0 -181
  109. package/lib/mongodb/writes/delete-one.js +0 -173
  110. package/lib/mongodb/writes/find-one-and-delete.js +0 -203
  111. package/lib/mongodb/writes/find-one-and-replace.js +0 -239
  112. package/lib/mongodb/writes/find-one-and-update.js +0 -240
  113. package/lib/mongodb/writes/increment-one.js +0 -259
  114. package/lib/mongodb/writes/index.js +0 -46
  115. package/lib/mongodb/writes/insert-batch.js +0 -508
  116. package/lib/mongodb/writes/insert-many.js +0 -223
  117. package/lib/mongodb/writes/insert-one.js +0 -169
  118. package/lib/mongodb/writes/replace-one.js +0 -226
  119. package/lib/mongodb/writes/result-handler.js +0 -237
  120. package/lib/mongodb/writes/update-batch.js +0 -416
  121. package/lib/mongodb/writes/update-many.js +0 -275
  122. package/lib/mongodb/writes/update-one.js +0 -273
  123. package/lib/mongodb/writes/upsert-one.js +0 -203
  124. package/lib/multi-level-cache.js +0 -244
  125. package/lib/operators.js +0 -330
  126. package/lib/redis-cache-adapter.js +0 -267
  127. package/lib/saga/SagaContext.js +0 -67
  128. package/lib/saga/SagaDefinition.js +0 -32
  129. package/lib/saga/SagaExecutor.js +0 -201
  130. package/lib/saga/SagaOrchestrator.js +0 -186
  131. package/lib/saga/index.js +0 -11
  132. package/lib/slow-query-log/base-storage.js +0 -70
  133. package/lib/slow-query-log/batch-queue.js +0 -97
  134. package/lib/slow-query-log/config-manager.js +0 -196
  135. package/lib/slow-query-log/index.js +0 -238
  136. package/lib/slow-query-log/mongodb-storage.js +0 -324
  137. package/lib/slow-query-log/query-hash.js +0 -39
  138. package/lib/sync/ChangeStreamSyncManager.js +0 -405
  139. package/lib/sync/ResumeTokenStore.js +0 -192
  140. package/lib/sync/SyncConfig.js +0 -127
  141. package/lib/sync/SyncTarget.js +0 -240
  142. package/lib/sync/index.js +0 -20
  143. package/lib/transaction/CacheLockManager.js +0 -162
  144. package/lib/transaction/DistributedCacheLockManager.js +0 -475
  145. package/lib/transaction/Transaction.js +0 -315
  146. package/lib/transaction/TransactionManager.js +0 -267
  147. package/lib/transaction/index.js +0 -11
  148. package/lib/utils/objectid-converter.js +0 -632
  149. package/types/README.md +0 -122
  150. package/types/base.ts +0 -94
  151. package/types/batch.ts +0 -187
  152. package/types/cache.ts +0 -71
  153. package/types/chain.ts +0 -254
  154. package/types/collection.ts +0 -357
  155. package/types/expression.ts +0 -109
  156. package/types/function-cache.d.ts +0 -135
  157. package/types/lock.ts +0 -95
  158. package/types/model/definition.ts +0 -152
  159. package/types/model/index.ts +0 -10
  160. package/types/model/instance.ts +0 -121
  161. package/types/model/relations.ts +0 -121
  162. package/types/model/virtuals.ts +0 -32
  163. package/types/monsqlize.ts +0 -245
  164. package/types/options.ts +0 -192
  165. package/types/pagination.ts +0 -154
  166. package/types/pool.ts +0 -125
  167. package/types/query.ts +0 -71
  168. package/types/saga.ts +0 -125
  169. package/types/stream.ts +0 -64
  170. package/types/sync.ts +0 -79
  171. package/types/transaction.ts +0 -79
  172. package/types/write.ts +0 -77
package/README.md CHANGED
@@ -1,1828 +1,537 @@
1
- <div align="center">
2
-
3
- # 🚀 monSQLize
4
-
5
- ### 🎯 统一数据库查询语法框架
6
-
7
- **当前**: MongoDB增强层(10~100倍性能 · 企业特性 · 零学习成本)
8
- **未来**: 让MySQL/PostgreSQL也能用MongoDB语法查询
9
-
10
- **mon**SQLize = **Mon**goDB + **SQL** = 一套语法,多种数据库
11
-
12
- [![npm version](https://img.shields.io/npm/v/monsqlize.svg)](https://www.npmjs.com/package/monsqlize)
13
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](./index.d.ts)
14
- [![Test Coverage](https://img.shields.io/badge/Coverage-90.77%25-brightgreen.svg)](./TEST-COVERAGE-REPORT.md)
15
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
16
- [![MongoDB](https://img.shields.io/badge/MongoDB-4.4%2B-green.svg)](https://www.mongodb.com/)
17
- [![Node.js](https://img.shields.io/badge/Node.js-16%2B-brightgreen)](https://nodejs.org/)
18
-
19
- ```bash
20
- npm install monsqlize
21
- ```
22
-
23
- [快速开始](#-快速开始) · [项目愿景](#-项目愿景) · [核心特性](#-核心特性) · [完整文档](./docs/INDEX.md) · [错误码参考](./docs/error-codes.md)
24
-
25
- </div>
26
-
27
- ---
28
-
29
- ## 📑 目录
30
-
31
- - [⚡ 性能对比](#-性能对比)
32
- - [🎯 项目愿景](#-项目愿景)
33
- - [💡 为什么选择 monSQLize?](#-为什么选择-monsqlize)
34
- - [🎯 何时使用 monSQLize?](#-何时使用-monsqlize)
35
- - [🚀 快速开始](#-快速开始)
36
- - [🌟 核心特性](#-核心特性)
37
- - [0. 🎯 统一表达式系统 🆕](#0--统一表达式系统--v109---让聚合查询像sql一样简单)
38
- - [1. 智能缓存系统](#1--智能缓存系统---性能提升-10100-倍)
39
- - [2. 🏢 企业级特性](#2--企业级特性)
40
- - [3. 📦 便利方法](#3--便利方法---减少-6080-代码)
41
- - [4. 🎯 可选Model层](#4--可选model层)
42
- - [5. 🔄 事务管理优化](#5--事务管理优化---减少-30-数据库访问)
43
- - [📊 性能测试报告](#-性能测试报告)
44
- - [🎨 完整功能清单](#-完整功能清单)
45
- - [🆚 MongoDB 原生驱动对比](#-与-mongodb-原生驱动对比)
46
- - [📖 完整文档](#-完整文档)
47
- - [🌍 兼容性](#-兼容性)
48
- - [🗺️ 产品路线图](#️-产品路线图)
49
- - [🤝 贡献指南](#-贡献指南)
50
- - [📄 许可证](#-许可证)
51
- - [💬 社区与支持](#-社区与支持)
52
-
53
- ---
54
-
55
- ## 性能对比
56
-
57
- ```javascript
58
- // MongoDB 原生驱动
59
- const users = await collection.find({ status: 'active' }).toArray(); // 50ms
60
- const product = await products.findOne({ _id: productId }); // 10ms
61
-
62
- // ✅ monSQLize(启用缓存)
63
- const users = await collection.find({ status: 'active' }, { cache: 60000 }); // 0.5ms ⚡ 100x faster
64
- const product = await products.findOne({ _id: productId }, { cache: 60000 }); // 0.1ms ⚡ 100x faster
65
- ```
66
-
67
- **只需在初始化时配置缓存,业务代码一行不改,性能立即提升!**
68
-
69
- ---
70
-
71
- ## 🎯 项目愿景
72
-
73
- **用MongoDB语法统一所有数据库查询**
74
-
75
- **mon**SQLize = **Mon**goDB + **SQL** = 统一查询语法
76
-
77
- ### 当前阶段(v1.0.x):MongoDB增强层
78
-
79
- 为MongoDB应用提供:
80
-
81
- - ⚡ **10~100倍性能提升** - L1(内存)+ L2(Redis)智能缓存,业界最完善
82
- - 🏢 **企业级特性** - 分布式锁、SSH隧道、慢查询监控(内置,零配置)
83
- - 🛠️ **56+增强方法** - 业界最完整,代码减少60~80%
84
- - 🎯 **可选Model层** - Schema验证、Hooks、Populate(6个方法支持)
85
- - **100% API兼容** - 零学习成本,渐进式采用
86
-
87
- <table>
88
- <tr>
89
- <td width="33%" align="center">
90
- <h3>⚡ 智能缓存</h3>
91
- <p>L1: 内存缓存 (LRU)<br>L2: Redis缓存<br>自动失效<br>10~100倍性能提升</p>
92
- </td>
93
- <td width="33%" align="center">
94
- <h3>🏢 企业特性</h3>
95
- <p>分布式锁<br>SSH隧道<br>慢查询监控<br>事务优化<br>批量操作</p>
96
- </td>
97
- <td width="33%" align="center">
98
- <h3>🛠️ 增强方法</h3>
99
- <p>56+个方法<br>代码减少60~80%<br>ObjectId自动转换<br>语义化API</p>
100
- </td>
101
- </tr>
102
- </table>
103
-
104
- ### 未来愿景(v2.0+):统一查询语法
105
-
106
- **革命性目标**: 让MySQL/PostgreSQL也能用MongoDB语法
107
-
108
- ```javascript
109
- // 同一套代码,支持多种数据库
110
- const users = await collection.find({
111
- age: { $gte: 18 },
112
- status: 'active'
113
- });
114
-
115
- // MongoDB - 当前已支持
116
- // MySQL - 🎯 未来自动转换为: SELECT * FROM users WHERE age >= 18 AND status = 'active'
117
- // PostgreSQL - 🎯 未来自动转换为: SELECT * FROM users WHERE age >= 18 AND status = 'active'
118
- ```
119
-
120
- **解决的核心痛点**:
121
- - ❌ 切换数据库需要重写所有查询代码
122
- - ❌ 团队需要学习多种查询语法
123
- - ❌ 跨数据库迁移成本极高
124
- - ❌ 多数据库项目维护复杂
125
-
126
- **monSQLize方案**:
127
- - ✅ 统一使用MongoDB查询语法(最直观、最灵活)
128
- - 底层自动适配不同数据库
129
- - 一套代码,多种数据库
130
- - ✅ 零迁移成本
131
-
132
- **了解更多**: 📖 [完整项目愿景文档](./docs/PROJECT-VISION.md)
133
-
134
- ---
135
-
136
- ## 💡 为什么选择 monSQLize?
137
-
138
- ### 你遇到的问题
139
-
140
- <table>
141
- <tr>
142
- <td width="50%">
143
-
144
- **😫 数据库性能瓶颈**
145
- - 高并发时查询变慢
146
- - 热点数据重复查询数据库
147
- - 聚合统计拖慢响应速度
148
- - 用户抱怨页面加载慢
149
-
150
- **😫 代码重复繁琐**
151
- - ObjectId 转换到处都是
152
- - 批量查询要写很多代码
153
- - Upsert 操作不够直观
154
- - 事务代码复杂易错
155
-
156
- **😫 多实例部署问题**
157
- - 缓存不一致导致脏读
158
- - 定时任务重复执行
159
- - 库存扣减并发冲突
160
- - 需要额外的锁机制
161
-
162
- </td>
163
- <td width="50%">
164
-
165
- **✅ monSQLize 的解决方案**
166
- - **智能缓存系统** - 热点数据走缓存,10~100倍性能提升
167
- - **自动失效机制** - 写操作自动清理,保证数据一致性
168
- - **缓存命中率 70~90%** - 真实业务场景验证
169
- - **响应时间 < 1ms** - 从 10~50ms 降至毫秒级
170
-
171
- **✅ monSQLize 的解决方案**
172
- - **便利方法** - findOneById、findByIds、upsertOne
173
- - **自动转换 ObjectId** - 无需手动处理
174
- - **语义化 API** - 代码更清晰易读
175
- - **事务自动管理** - withTransaction 简化事务代码
176
-
177
- **✅ monSQLize 的解决方案**
178
- - **Redis 广播** - 多实例缓存自动同步
179
- - **分布式锁** - 解决并发控制问题
180
- - **定时任务防重** - tryAcquireLock 机制
181
- - **开箱即用** - 配置简单,无需额外组件
182
-
183
- </td>
184
- </tr>
185
- </table>
186
-
187
- ### 真实效果
188
-
189
- | 场景 | 优化前 | 优化后 | 提升 |
190
- |------|--------|--------|------|
191
- | **商品详情页** | 50ms/次 | 0.5ms/次 | **100x** ⚡ |
192
- | **用户列表** | 80ms/次 | 0.8ms/次 | **100x** ⚡ |
193
- | **订单统计** | 200ms/次 | 2ms/次 | **100x** ⚡ |
194
- | **批量插入 10万条** | 30s | 1.2s | **25x** ⚡ |
195
-
196
- **缓存命中率**:电商 85% · 内容平台 75% · 社交应用 80%
197
-
198
- ---
199
-
200
- ## 🎯 何时使用 monSQLize?
201
-
202
- ### ✅ 适合的场景
203
-
204
- | 场景 | 说明 | 预期效果 |
205
- |------|------|---------|
206
- | **高并发读取** | 商品详情、用户信息等热点数据 | 缓存命中率 70~90%,响应时间从 10~50ms 降至 < 1ms |
207
- | **复杂查询** | 聚合统计、关联查询 | 重复查询直接走缓存,避免重复计算 |
208
- | **多实例部署** | 负载均衡、水平扩展 | Redis 广播保证缓存一致性 |
209
- | **事务密集** | 订单、支付等业务 | 自动管理事务,优化只读操作 |
210
- | **并发控制** | 库存扣减、定时任务 | 分布式锁解决复杂并发场景 |
211
-
212
- ### ⚠️ 不适合的场景
213
-
214
- | 场景 | 原因 | 建议 |
215
- |------|------|------|
216
- | **纯写入应用** | 大量写入,很少查询 | 缓存作用有限,使用原生驱动即可 |
217
- | **实时性要求极高** | 必须每次查询最新数据 | 不启用缓存,或使用极短 TTL |
218
- | **简单 CRUD** | 简单应用,流量不大 | 原生驱动足够,无需引入复杂度 |
219
- | **内存受限** | 服务器内存紧张 | 缓存会占用额外内存 |
220
-
221
- ### 💡 使用建议
222
-
223
- - **渐进式采用**:先在热点查询启用缓存,观察效果后逐步扩展
224
- - **监控指标**:关注缓存命中率、内存使用、慢查询日志
225
- - **合理配置**:根据业务特点调整 TTL、缓存大小
226
- - **混合使用**:可与原生驱动混用,性能敏感用 monSQLize,简单查询用原生
227
-
228
- ---
229
-
230
-
231
- ## �️ 文档导航
232
-
233
- ### 📚 核心概念(8 篇)
234
- [连接管理](./docs/connection.md) · [ObjectId 自动转换](./docs/objectid-auto-convert.md) 🆕 · [缓存系统](./docs/cache.md) · [事务管理](./docs/transaction.md) · [Model 层](./docs/model.md) · [业务锁](./docs/business-lock.md) · [SSH 隧道](./docs/ssh-tunnel.md) · [分布式部署](./docs/distributed-deployment.md)
235
-
236
- ### 🔍 查询操作(8 篇)
237
- [find](./docs/find.md) · [findOne](./docs/findOne.md) · [findOneById](./docs/find-one-by-id.md) · [findByIds](./docs/find-by-ids.md) · [findPage](./docs/findPage.md) · [count](./docs/count.md) · [distinct](./docs/distinct.md) · [watch](./docs/watch.md) ⭐
238
-
239
- ### ✏️ 写入操作(15 篇)
240
- **插入**: [insertOne](./docs/insert-one.md) · [insertMany](./docs/insert-many.md) · [insertBatch](./docs/insertBatch.md)
241
- **更新**: [updateOne](./docs/update-one.md) · [updateMany](./docs/update-many.md) · [updateBatch](./docs/updateBatch.md) · [replaceOne](./docs/replace-one.md) · [findOneAndUpdate](./docs/find-one-and-update.md) · [findOneAndReplace](./docs/find-one-and-replace.md)
242
- **删除**: [deleteOne](./docs/delete-one.md) · [deleteMany](./docs/delete-many.md) · [deleteBatch](./docs/deleteBatch.md) · [findOneAndDelete](./docs/find-one-and-delete.md)
243
- **便利方法**: [upsertOne](./docs/upsert-one.md) · [incrementOne](./docs/increment-one.md) · [findAndCount](./docs/find-and-count.md)
244
-
245
- ### 📊 聚合与工具(10+ 篇)
246
- [aggregate](./docs/aggregate.md) · [explain](./docs/explain.md) · [链式调用](./docs/chaining-api.md) ⭐ · [索引管理](./docs/create-index.md) · [Count 队列](./docs/count-queue.md) ⭐ · [慢查询日志](./docs/slow-query-log.md) · [书签管理](./docs/bookmarks.md) · [ESM 支持](./docs/esm-support.md)
247
-
248
- **完整文档索引**: [docs/INDEX.md](./docs/INDEX.md) - 60+ 篇详细文档
249
-
250
- ---
251
-
252
- ## �🚀 快速开始
253
-
254
- ### 安装
255
-
256
- ```bash
257
- npm install monsqlize
258
- ```
259
-
260
- **自动安装的依赖**:
261
- - ✅ `mongodb` - MongoDB 官方驱动
262
- - ✅ `schema-dsl` - Schema 验证库(Model 层必需)
263
- - ✅ `ssh2` - SSH 隧道支持
264
-
265
- **可选依赖**:
266
- - ⚠️ `ioredis` - Redis 多层缓存(启用 L2 缓存需要)
267
-
268
- ### 基础使用
269
-
270
- ```javascript
271
- const MonSQLize = require('monsqlize');
272
-
273
- // 1. 初始化并连接
274
- const msq = new MonSQLize({
275
- type: 'mongodb',
276
- databaseName: 'mydb',
277
- config: { uri: 'mongodb://localhost:27017' },
278
- cache: { enabled: true, ttl: 60000 } // 启用缓存,60秒过期
279
- });
280
-
281
- await msq.connect();
282
-
283
- // 2. 获取集合
284
- const users = msq.collection('users');
285
-
286
- // 3. 基础查询(自动缓存)
287
- const user = await users.findOne({ email: 'test@example.com' });
288
-
289
- // 4. 插入数据
290
- await users.insertOne({
291
- username: 'john',
292
- email: 'john@example.com',
293
- createdAt: new Date()
294
- });
295
-
296
- // 5. 更新数据(自动清除缓存)
297
- await users.updateOne(
298
- { email: 'test@example.com' },
299
- { $set: { lastLogin: new Date() } }
300
- );
301
-
302
- // 6. 便利方法(自动转换ObjectId)
303
- const userById = await users.findOneById('507f1f77bcf86cd799439011');
304
-
305
- // 7. 关闭连接
306
- await msq.close();
307
- ```
308
-
309
- **就这么简单!** 完全兼容MongoDB原生API,只需初始化时启用缓存,业务代码零改动。
310
-
311
- ### 使用 Model 层(可选)
312
-
313
- 如果需要 **Schema验证**、**Populate关联查询**、**Hooks生命周期** 等 ORM 特性,可以使用 Model 层。
314
-
315
- > **📦 依赖说明**: Model 层需要 `schema-dsl` 包支持(已随 monsqlize 自动安装,无需额外操作)
316
-
317
- Model 层有两种使用方式,二者**互斥**,选其一即可:
318
-
319
- | 方式 | 适合场景 |
320
- |------|---------|
321
- | **手动注册**(`Model.define()`)| 少量 Model、测试环境、需要精确控制加载顺序 |
322
- | **自动加载**(`models:` 配置项)| 生产环境,Model 文件统一放在一个目录下 |
323
-
324
- #### 方式一:手动注册
325
-
326
- ```javascript
327
- const MonSQLize = require('monsqlize');
328
- const { Model } = MonSQLize;
329
-
330
- // 1. 先在 connect() 之前调用 Model.define() 注册所有 Model
331
- Model.define('users', {
332
- schema: (dsl) => dsl({
333
- username: 'string:3-32!',
334
- email: 'email!',
335
- password: 'string:6-!',
336
- age: 'number:0-120'
337
- }),
338
- relations: {
339
- posts: { from: 'posts', localField: '_id', foreignField: 'userId', single: false }
340
- },
341
- hooks: (model) => ({
342
- insert: { before: async (ctx, doc) => { doc.createdAt = new Date(); return doc; } }
343
- }),
344
- methods: (model) => ({
345
- instance: { checkPassword(password) { return this.password === password; } },
346
- static: { async findByUsername(username) { return await model.findOne({ username }); } }
347
- })
348
- });
349
-
350
- Model.define('posts', {
351
- schema: (dsl) => dsl({ title: 'string:1-200!', content: 'string!', userId: 'string!' })
352
- });
353
-
354
- // 2. 创建实例并连接
355
- const msq = new MonSQLize({
356
- type: 'mongodb',
357
- databaseName: 'mydb',
358
- config: { uri: 'mongodb://localhost:27017' },
359
- cache: { enabled: true }
360
- });
361
- await msq.connect();
362
-
363
- // 3. 获取 Model 并使用
364
- const User = msq.model('users');
365
- ```
366
-
367
- #### 方式二:自动加载(推荐用于生产环境)
368
-
369
- 将每个 Model 单独放在一个文件里,`connect()` 时自动扫描目录加载,无需手动 `Model.define()`:
370
-
371
- ```javascript
372
- // app.js
373
- const path = require('path');
374
-
375
- const msq = new MonSQLize({
376
- type: 'mongodb',
377
- databaseName: 'mydb',
378
- config: { uri: 'mongodb://localhost:27017' },
379
- // 推荐用绝对路径,避免受 process.cwd() 影响
380
- models: path.join(__dirname, 'models')
381
- // 或完整配置:
382
- // models: { path: path.join(__dirname, 'models'), pattern: '*.model.js', recursive: true }
383
- });
384
-
385
- await msq.connect(); // ← 自动扫描 models/*.model.{js,ts,mjs,cjs}
386
-
387
- const User = msq.model('users'); // 直接使用,无需 Model.define()
388
- ```
389
-
390
- > 相对路径(如 `'./models'`)以 `process.cwd()` 为基准,即 Node.js 进程的启动目录。为避免歧义,推荐始终使用 `path.join(__dirname, 'models')` 这样的绝对路径。
391
-
392
- ```javascript
393
- // models/user.model.js ← 每个 Model 独立一个文件
394
- module.exports = {
395
- name: 'users', // 集合名称(必需)
396
- schema: (dsl) => dsl({
397
- username: 'string:3-32!',
398
- email: 'email!'
399
- }),
400
- methods: (model) => ({
401
- static: {
402
- async findByUsername(username) { return await model.findOne({ username }); }
403
- }
404
- })
405
- };
406
- ```
407
-
408
- > 详细说明(完整配置项、文件格式、错误处理)见 [docs/model.md Model 自动加载](./docs/model.md#model-自动加载v107)
409
-
410
- #### 两种方式共同的后续操作
411
-
412
- ```javascript
413
-
414
- // ✅ Schema 验证自动生效
415
- try {
416
- await User.insertOne({
417
- username: 'jo', // ❌ 太短,验证失败
418
- email: 'invalid-email', // ❌ 邮箱格式错误
419
- age: 25
420
- });
421
- } catch (err) {
422
- console.error(err.code); // 'VALIDATION_ERROR'
423
- console.error(err.errors); // 详细的验证错误
424
- }
425
-
426
- // 正确的数据
427
- const user = await User.insertOne({
428
- username: 'john',
429
- email: 'john@example.com',
430
- password: 'secret123',
431
- age: 25
432
- // createdAt hook 自动添加
433
- });
434
-
435
- // 使用自定义方法
436
- const foundUser = await User.findByUsername('john');
437
- if (foundUser.checkPassword('secret123')) {
438
- console.log('登录成功');
439
- }
440
-
441
- // Populate 关联查询(自动填充用户的文章)
442
- const userWithPosts = await User.findOne({ username: 'john' })
443
- .populate('posts');
444
-
445
- console.log(userWithPosts.posts); // [{ title: '...', content: '...' }, ...]
446
-
447
- // 禁用验证(特殊场景)
448
- await User.insertOne(doc, { skipValidation: true });
449
- ```
450
-
451
- **Model 层特性**:
452
- - **Schema 验证** - 自动验证数据格式(基于 `schema-dsl` 库,v1.0.7 默认启用)
453
- - **自动加载** - 扫描目录自动加载 Model 文件(v1.0.7+)
454
- - **Populate** - 关联查询,支持 6 个方法(业界领先)
455
- - ✅ **Hooks** - 生命周期钩子(insert/update/delete/find)
456
- - **Relations** - 定义表关系(hasOne/hasMany/belongsTo)
457
- - ✅ **自定义方法** - instance 方法注入到文档,static 方法挂载到 Model
458
- - ✅ **自动缓存** - Populate 查询结果也会缓存
459
- - ✅ **数据源绑定** - `connection: { pool?, database? }` 绑定指定连接池和/或数据库(v1.2.2+)
460
-
461
- **数据源绑定示例(v1.2.2+)**:
462
-
463
- ```js
464
- // 在多连接池场景中,将 Model 绑定到指定的连接池 + 数据库
465
- const msq = new MonSQLize({
466
- uri: 'mongodb://localhost:27017',
467
- databaseName: 'main_db',
468
- pools: [{ name: 'analytics', uri: 'mongodb://analytics-host:27017' }]
469
- });
470
-
471
- // 绑定到不同数据库(使用默认连接池)
472
- Model.define('AuditLog', {
473
- schema: (dsl) => dsl({ action: 'string!', userId: 'string!' }),
474
- connection: { database: 'audit_db' }
475
- });
476
-
477
- // 绑定到不同连接池 + 不同数据库
478
- Model.define('AnalyticsReport', {
479
- schema: (dsl) => dsl({ reportId: 'string!', data: 'object' }),
480
- connection: { pool: 'analytics', database: 'reports_db' }
481
- });
482
-
483
- // 调用时自动路由,无需手动切换
484
- const AuditLogModel = msq.model('AuditLog'); // → audit_db(默认池)
485
- const ReportModel = msq.model('AnalyticsReport'); // → reports_db(analytics 池)
486
- const UserModel = msq.model('users'); // → main_db(原逻辑,向后兼容)
487
- ```
488
-
489
- 📖 **详细文档**:[Model 层完整指南](./docs/model.md) | [Populate API](./docs/populate.md) | [Hooks API](./docs/hooks.md) | [Schema 验证](./docs/model.md#schema-验证)
490
-
491
- ---
492
-
493
- ### 从原生驱动迁移
494
-
495
- ```javascript
496
- // 原来的代码
497
- const { MongoClient } = require('mongodb');
498
- const client = await MongoClient.connect('mongodb://localhost:27017');
499
- const db = client.db('mydb');
500
- const users = db.collection('users');
501
-
502
- // 迁移后(只需改初始化)
503
- const MonSQLize = require('monsqlize');
504
- const msq = new MonSQLize({
505
- type: 'mongodb',
506
- databaseName: 'mydb', // 数据库名称
507
- config: { uri: 'mongodb://localhost:27017' },
508
- cache: { enabled: true } // 启用缓存
509
- });
510
- await msq.connect();
511
- const users = msq.collection('users');
512
-
513
- // ✅ 后续代码完全不变
514
- const user = await users.findOne({ email: 'test@example.com' });
515
- ```
516
-
517
- ---
518
-
519
- ## 🌟 核心特性
520
-
521
- ### 0. 🎨 通用函数缓存 🆕 v1.1.4 - 为任意函数添加缓存
522
-
523
- **52个测试(100% 通过)**,为任意异步函数添加缓存能力,性能提升**50000x**!
524
-
525
- <table>
526
- <tr>
527
- <td width="50%">
528
-
529
- **🆕 装饰器模式**
530
-
531
- ```javascript
532
- const { withCache } = require('monsqlize');
533
-
534
- // 业务函数
535
- async function getUserProfile(userId) {
536
- const user = await msq.collection('users')
537
- .findOne({ _id: userId });
538
- const orders = await msq.collection('orders')
539
- .find({ userId }).toArray();
540
- return { user, orders };
541
- }
542
-
543
- // 添加缓存(零侵入)
544
- const cached = withCache(getUserProfile, {
545
- ttl: 300000, // 5分钟
546
- cache: msq.getCache()
547
- });
548
-
549
- // 使用
550
- await cached('user123'); // 首次:查询数据库
551
- await cached('user123'); // 再次:从缓存读取 ⚡
552
- ```
553
-
554
- </td>
555
- <td width="50%">
556
-
557
- **核心优势**
558
-
559
- - ✅ **零侵入** - 装饰器模式,不修改原函数
560
- - ✅ **自动序列化** - 支持复杂参数(对象、Date等)
561
- - ✅ **并发控制** - 防止缓存击穿
562
- - ✅ **双层缓存** - 本地 + Redis,最佳性能
563
- - ✅ **条件缓存** - 基于返回值决定是否缓存
564
- - ✅ **统计监控** - 命中率、调用次数等
565
- - ✅ **命名空间** - 多模块缓存隔离
566
- - ✅ **TypeScript** - 完整类型支持
567
-
568
- **性能提升**:
569
- - 🚀 复杂业务函数:50000x
570
- - 🚀 外部 API 调用:200000x
571
- - 🚀 复杂计算:100000x
572
-
573
- </td>
574
- </tr>
575
- </table>
576
-
577
- **FunctionCache 类管理**:
578
-
579
- ```javascript
580
- const { FunctionCache } = require('monsqlize');
581
-
582
- const fnCache = new FunctionCache(msq, {
583
- namespace: 'myApp',
584
- defaultTTL: 60000
585
- });
586
-
587
- // 注册多个函数
588
- fnCache.register('getUserProfile', getUserProfileFn);
589
- fnCache.register('getOrderStats', getOrderStatsFn);
590
-
591
- // 执行
592
- await fnCache.execute('getUserProfile', 'user123');
593
-
594
- // 失效缓存
595
- await fnCache.invalidate('getUserProfile', 'user123');
596
-
597
- // 查看统计
598
- const stats = fnCache.getStats('getUserProfile');
599
- console.log('命中率:', stats.hitRate);
600
- ```
601
-
602
- 📖 [完整文档](./docs/function-cache.md) · [键生成机制](./docs/function-cache-key-generation.md)
603
-
604
- ---
605
-
606
- ### 1. 🎯 统一表达式系统 🆕 v1.1.0 - 让聚合查询像SQL一样简单
607
-
608
- **122个操作符(100% MongoDB支持!新增49个函数)**,让MongoDB聚合查询**像写SQL一样简单**!
609
-
610
- <table>
611
- <tr>
612
- <td width="50%">
613
-
614
- **🆕 统一表达式语法**
615
-
616
- ```javascript
617
- const { expr } = require('monsqlize');
618
-
619
- // ❌ MongoDB原生(繁琐)
620
- await users.aggregate([
621
- {
622
- $project: {
623
- fullName: {
624
- $concat: ['$firstName', ' ', '$lastName']
625
- },
626
- age: {
627
- $subtract: [
628
- { $year: new Date() },
629
- { $year: '$birthDate' }
630
- ]
631
- }
632
- }
633
- }
634
- ]);
635
-
636
- // ✅ 统一表达式(简洁)
637
- await users.aggregate([
638
- {
639
- $project: {
640
- fullName: expr("CONCAT(firstName, ' ', lastName)"),
641
- age: expr("YEAR(CURRENT_DATE) - YEAR(birthDate)")
642
- }
643
- }
644
- ]);
645
- ```
646
-
647
- </td>
648
- <td width="50%">
649
-
650
- **核心优势**
651
-
652
- - ✅ **67个操作符** - 覆盖95%使用场景
653
- - ✅ **类SQL语法** - 易读易写,降低学习成本
654
- - ✅ **上下文感知** - 自动适配$match/$project/$group
655
- - ✅ **Lambda表达式** - FILTER/MAP完整支持
656
- - ✅ **高性能** - LRU缓存,>90%命中率
657
- - ✅ **100%兼容** - 可与原生语法混用
658
-
659
- **支持的操作符分类**:
660
- - 🔹 条件判断 (三元、SWITCH)
661
- - 🔹 数学计算 (ABS、ROUND、POW等)
662
- - 🔹 字符串处理 (CONCAT、SPLIT、REPLACE等)
663
- - 🔹 数组操作 (FILTER、MAP、SIZE等)
664
- - 🔹 日期处理 (YEAR、MONTH、DAY等)
665
- - 🔹 类型转换 (TO_INT、TO_STRING等)
666
-
667
- </td>
668
- </tr>
669
- </table>
670
-
671
- **更多示例**:
672
-
673
- ```javascript
674
- // 条件判断 - 三元运算符
675
- expr("score >= 90 ? 'A' : 'B'")
676
-
677
- // 多分支条件 - SWITCH
678
- expr("SWITCH(score >= 90, 'A', score >= 80, 'B', score >= 60, 'C', 'F')")
679
-
680
- // 字符串处理
681
- expr("UPPER(TRIM(email))")
682
- expr("SPLIT(tags, ',')")
683
-
684
- // 数组过滤(Lambda表达式)
685
- expr("FILTER(items, item, item.price > 100)")
686
-
687
- // 日期计算
688
- expr("YEAR(createdAt) === 2024 && MONTH(createdAt) === 12")
689
-
690
- // 完整聚合查询示例
691
- await orders.aggregate([
692
- {
693
- $project: {
694
- // 价格计算
695
- finalPrice: expr("price * (1 - discount / 100)"),
696
-
697
- // 日期提取
698
- year: expr("YEAR(createdAt)"),
699
- month: expr("MONTH(createdAt)"),
700
-
701
- // 状态分类
702
- statusLabel: expr("SWITCH(status === 'paid', 'Paid', status === 'pending', 'Pending', 'Cancelled')")
703
- }
704
- },
705
- {
706
- $group: {
707
- _id: { year: '$year', month: '$month' },
708
- totalOrders: expr("COUNT()"),
709
- totalRevenue: expr("SUM(finalPrice)")
710
- }
711
- }
712
- ]);
713
- ```
714
-
715
- 📖 **完整文档**:[统一表达式系统](./docs/aggregate.md#统一表达式系统) | [67个操作符列表](./docs/aggregate.md#支持的操作符-67个)
716
-
717
- ---
718
-
719
- ### 2. ⚡ 智能缓存系统 - 性能提升 10~100 倍
720
-
721
- <table>
722
- <tr>
723
- <td width="50%">
724
-
725
- **特性**
726
-
727
- - ✅ **TTL 过期策略** - 指定缓存时间
728
- - ✅ **LRU 淘汰策略** - 自动淘汰旧数据
729
- - ✅ **精准失效 🆕** - 只清除受影响的缓存
730
- - ✅ **自动失效** - 写操作自动清理缓存
731
- - ✅ **并发去重** - 相同查询只执行一次
732
- - ✅ **多层缓存** - 内存 + Redis
733
- - ✅ **命名空间隔离** - 按集合独立管理
734
-
735
- </td>
736
- <td width="50%">
737
-
738
- **性能提升**
739
-
740
- | 操作 | 原生驱动 | monSQLize | 提升 |
741
- |------|---------|-----------|------|
742
- | 热点查询 | 50ms | 0.5ms | **100x** ⚡ |
743
- | 复杂聚合 | 200ms | 2ms | **100x** ⚡ |
744
- | 列表查询 | 30ms | 0.3ms | **100x** ⚡ |
745
-
746
- </td>
747
- </tr>
748
- </table>
749
-
750
- ```javascript
751
- // 一行代码启用缓存
752
- const users = await collection.find({ status: 'active' }, { cache: 60000 });
753
- ```
754
-
755
- ### 2. 🔄 事务管理优化 - 减少 30% 数据库访问
756
-
757
- ```javascript
758
- // 自动管理事务生命周期
759
- await db.withTransaction(async (tx) => {
760
- // 只读操作会被优化(不加锁,减少 30% 访问)
761
- const user = await users.findOne({ _id: userId }, { session: tx.session });
762
-
763
- // 写操作自动加锁
764
- await users.updateOne({ _id: userId }, { $inc: { balance: -100 } }, { session: tx.session });
765
-
766
- // 自动提交 or 回滚
767
- });
768
- ```
769
-
770
- ### 2.5 🔀 Saga 分布式事务 - 跨服务事务协调 🆕
771
-
772
- ```javascript
773
- // 定义 Saga(跨服务事务)
774
- msq.defineSaga({
775
- name: 'create-order-with-payment',
776
- steps: [
777
- {
778
- name: 'create-order',
779
- execute: async (ctx) => {
780
- const order = await createOrder(ctx.data);
781
- // ✅ 可以保存字符串、对象、数组等任何类型
782
- ctx.set('order', order); // 保存完整对象
783
- return order;
784
- },
785
- compensate: async (ctx) => {
786
- const order = ctx.get('order');
787
- await cancelOrder(order.id);
788
- }
789
- },
790
- {
791
- name: 'charge-payment',
792
- execute: async (ctx) => {
793
- const charge = await stripe.charges.create({...});
794
- ctx.set('charge', charge); // 保存完整对象
795
- return charge;
796
- },
797
- compensate: async (ctx) => {
798
- const charge = ctx.get('charge');
799
- await stripe.refunds.create({ charge: charge.id });
800
- }
801
- }
802
- ]
803
- });
804
-
805
- // 执行 Saga(失败自动补偿)
806
- const result = await msq.executeSaga('create-order-with-payment', data);
807
- ```
808
-
809
- **Saga 特性**:
810
- - ✅ 跨服务事务协调
811
- - ✅ 失败自动补偿(逆序执行)
812
- - ✅ 支持 Redis 分布式(多进程共享)
813
- - ✅ 无时间限制(突破 60秒限制)
814
- - ✅ 详细日志(完整执行追踪)
815
-
816
- [完整文档](./docs/saga-transaction.md)
817
-
818
- ---
819
-
820
- #### 🆕 Change Stream 数据同步 (v1.0.9)
821
-
822
- **实时同步数据到备份库,基于 MongoDB Change Stream**
823
-
824
- ```javascript
825
- const msq = new MonSQLize({
826
- type: 'mongodb',
827
- config: {
828
- uri: 'mongodb://localhost:27017/main',
829
- replicaSet: 'rs0' // 🔴 必须:Change Stream 需要 Replica Set
830
- },
831
-
832
- // 🆕 同步配置
833
- sync: {
834
- enabled: true,
835
- targets: [
836
- {
837
- name: 'backup-main',
838
- uri: 'mongodb://backup:27017/backup',
839
- collections: ['users', 'orders']
840
- }
841
- ]
842
- }
843
- });
844
-
845
- await msq.connect();
846
-
847
- // 正常使用,自动同步
848
- await msq.collection('users').insertOne({ name: 'Alice' });
849
- // ✅ 自动通过 Change Stream 同步到 backup-main
850
- ```
851
-
852
- **Change Stream 特性**:
853
- - ✅ 实时同步(延迟 10-500ms)
854
- - ✅ 断点续传(Resume Token)
855
- - ✅ 多目标支持(多地容灾)
856
- - ✅ 数据过滤和转换
857
- - ✅ 自动重连和健康检查
858
- - ✅ 主库影响 <2%(异步处理)
859
-
860
- [完整文档](./docs/sync-backup.md)
861
-
862
- ### 4. 📦 便利方法 - 减少 60~80% 代码
863
-
864
- <table>
865
- <tr>
866
- <td width="50%">
867
-
868
- **❌ 原生驱动**
869
-
870
- ```javascript
871
- // 查询单个文档(需要手动转换 ObjectId)
872
- const { ObjectId } = require('mongodb');
873
- const user = await users.findOne({
874
- _id: new ObjectId(userId)
875
- });
876
-
877
- // 批量查询(需要手动构建 $in)
878
- const userList = await users.find({
879
- _id: { $in: ids.map(id => new ObjectId(id)) }
880
- }).toArray();
881
-
882
- // Upsert(需要手动设置选项)
883
- await users.updateOne(
884
- { email: 'alice@example.com' },
885
- { $set: { name: 'Alice', age: 30 } },
886
- { upsert: true }
887
- );
888
- ```
889
-
890
- </td>
891
- <td width="50%">
892
-
893
- **✅ monSQLize**
894
-
895
- ```javascript
896
- // 查询单个文档(自动转换)
897
- const user = await users.findOneById(userId);
898
-
899
-
900
-
901
-
902
- // 批量查询(一行搞定)
903
- const userList = await users.findByIds(ids);
904
-
905
-
906
-
907
-
908
- // Upsert(语义化)
909
- await users.upsertOne(
910
- { email: 'alice@example.com' },
911
- { name: 'Alice', age: 30 }
912
- );
913
- ```
914
-
915
- **代码减少 60~80%!**
916
-
917
- </td>
918
- </tr>
919
- </table>
920
-
921
- **🔥 ObjectId 自动转换** - 告别手动转换
922
-
923
- ```javascript
924
- // ❌ 原生驱动 - 每次都要转换
925
- const { ObjectId } = require('mongodb');
926
- await users.findOne({ _id: new ObjectId(userId) });
927
- await users.find({ _id: { $in: ids.map(id => new ObjectId(id)) } }).toArray();
928
-
929
- // ✅ monSQLize - 自动识别并转换
930
- await users.findOneById(userId); // 自动转换字符串
931
- await users.findByIds([id1, id2, id3]); // 批量自动转换
932
- await users.findOne({ _id: userId }); // 查询时也自动转换
933
- ```
934
-
935
- ### 4. 🌐 分布式部署支持
936
-
937
- ```javascript
938
- // 多实例部署,Redis 自动同步缓存
939
- const db = new MonSQLize({
940
- cache: {
941
- distributed: {
942
- enabled: true,
943
- redis: redisInstance // 使用 Redis 广播缓存失效
944
- }
945
- }
946
- });
947
-
948
- // 实例 A 更新数据
949
- await users.updateOne({ _id: userId }, { $set: { name: 'Bob' } });
950
- // ⚡ 实例 B/C/D 的缓存自动失效
951
- ```
952
-
953
- ### 5. 🆕 业务级分布式锁(v1.4.0)
954
-
955
- ```javascript
956
- // 🔥 解决复杂业务场景的并发问题
957
-
958
- // 场景1:库存扣减
959
- await db.withLock(`inventory:${sku}`, async () => {
960
- const product = await inventory.findOne({ sku });
961
- const price = calculatePrice(product, user, coupon); // 复杂计算
962
- if (user.balance < price) throw new Error('余额不足');
963
-
964
- await inventory.updateOne({ sku }, { $inc: { stock: -1 } });
965
- await users.updateOne({ userId }, { $inc: { balance: -price } });
966
- await orders.insertOne({ userId, sku, price });
967
- });
968
-
969
- // 场景2:定时任务防重(多实例环境)
970
- const lock = await db.tryAcquireLock('cron:daily-report');
971
- if (lock) {
972
- try {
973
- await generateDailyReport(); // 只有一个实例执行
974
- } finally {
975
- await lock.release();
976
- }
977
- }
978
- ```
979
-
980
- **特性**:基于 Redis · 自动重试 · TTL 防死锁 · 支持续期 · 降级策略
981
-
982
- [📖 完整文档](./docs/business-lock.md)
983
-
984
- ### 6. 🚀 高性能批量插入
985
-
986
- ```javascript
987
- // 批量插入 10 万条数据
988
- await users.insertBatch(documents, {
989
- batchSize: 1000, // 每批 1000 条
990
- retryTimes: 3, // 失败重试 3 次
991
- onProgress: (stats) => {
992
- console.log(`进度: ${stats.inserted}/${stats.total}`);
993
- }
994
- });
995
- ```
996
-
997
- **性能**: 比原生 `insertMany` 快 **10~50 倍** ⚡
998
-
999
- ### 7. 📊 深度分页 - 支持千万级数据
1000
-
1001
- ```javascript
1002
- // 千万级数据分页(游标分页,性能稳定)
1003
- const result = await users.findPage({
1004
- query: { status: 'active' },
1005
- page: 1000, // 第 1000 页
1006
- limit: 20,
1007
- totals: {
1008
- mode: 'async', // 异步统计总数
1009
- ttl: 300000 // 缓存 5 分钟
1010
- }
1011
- });
1012
-
1013
- console.log(`总计: ${result.totals.total}, 共 ${result.totals.totalPages} 页`);
1014
- ```
1015
-
1016
- ### 8. 🛠️ 运维监控(开箱即用)
1017
-
1018
- ```javascript
1019
- // 🆕 慢查询日志持久化存储(v1.3+)
1020
- const msq = new MonSQLize({
1021
- type: 'mongodb',
1022
- config: { uri: 'mongodb://localhost:27017/mydb' },
1023
- slowQueryMs: 500,
1024
- slowQueryLog: true // ✅ 零配置启用,自动存储到 admin.slow_query_logs
1025
- });
1026
-
1027
- await msq.connect();
1028
-
1029
- // 查询慢查询日志(支持去重聚合)
1030
- const logs = await msq.getSlowQueryLogs(
1031
- { collection: 'users' },
1032
- { sort: { count: -1 }, limit: 10 } // 查询高频慢查询Top10
1033
- );
1034
- // [{ queryHash: 'abc123', count: 2400, avgTimeMs: 520, maxTimeMs: 1200, ... }]
1035
-
1036
- // 自动记录慢查询(原有功能)
1037
- // [WARN] Slow query { ns: 'mydb.users', duration: 1200ms, query: {...} }
1038
-
1039
- // 健康检查
1040
- const health = await db.health();
1041
- // { status: 'ok', uptime: 3600, connections: 10 }
1042
-
1043
- // 性能指标
1044
- const stats = await db.getStats();
1045
- // { queries: 10000, cacheHits: 9000, hitRate: 0.9 }
1046
- ```
1047
-
1048
- ### 9. 🔐 SSH隧道 - 安全连接内网数据库(v1.3+)
1049
-
1050
- ```javascript
1051
- // 场景:数据库位于防火墙后,无法直接访问
1052
- const db = new MonSQLize({
1053
- type: 'mongodb',
1054
- config: {
1055
- // SSH隧道配置
1056
- ssh: {
1057
- host: 'bastion.example.com', // SSH服务器(跳板机)
1058
- port: 22,
1059
- username: 'deploy',
1060
- password: 'your-password', // ✅ 支持密码认证
1061
- // 或使用私钥认证(推荐)
1062
- // privateKeyPath: '~/.ssh/id_rsa',
1063
- },
1064
- // MongoDB连接配置(内网地址,自动从URI解析remoteHost和remotePort)
1065
- uri: 'mongodb://user:pass@internal-mongo:27017/mydb'
1066
- }
1067
- });
1068
-
1069
- await db.connect(); // 自动建立SSH隧道
1070
- // 正常使用MongoDB,无需关心隧道细节
1071
- const users = db.collection('users');
1072
- const data = await users.findOne({});
1073
- await db.close(); // 自动关闭SSH隧道
1074
- ```
1075
-
1076
- **特性**:
1077
- - ✅ 支持密码和私钥认证
1078
- - ✅ 自动管理隧道生命周期
1079
- - ✅ 完美跨平台(基于ssh2库)
1080
- - ✅ 开箱即用,零额外配置
1081
-
1082
- [📖 SSH隧道详细文档](./docs/ssh-tunnel.md)
1083
-
1084
- ---
1085
-
1086
- ### 10. 🔄 ObjectId 跨版本兼容(v1.1.1+)🆕
1087
-
1088
- 解决混用 mongoose 和 monSQLize 时的 BSON 版本冲突问题。
1089
-
1090
- ```javascript
1091
- // ❌ 问题场景:mongoose (bson@4.x/5.x) + monSQLize (bson@6.x)
1092
- const dataFromMongoose = await MongooseModel.findOne({ ... }).lean();
1093
- await msq.collection('orders').insertOne(dataFromMongoose);
1094
- // 错误:Unsupported BSON version, bson types must be from bson 6.x.x
1095
-
1096
- // ✅ monSQLize v1.1.1+ 自动处理
1097
- const dataFromMongoose = await MongooseModel.findOne({ ... }).lean();
1098
- await msq.collection('orders').insertOne(dataFromMongoose);
1099
- // 成功:自动将旧版本 ObjectId 转换为 bson@6.x
1100
- ```
1101
-
1102
- **特性**:
1103
- - ✅ 自动检测并转换来自其他 BSON 版本的 ObjectId
1104
- - ✅ 递归处理嵌套对象和数组
1105
- - ✅ 性能优化:无需转换时零拷贝
1106
- - ✅ 错误降级:转换失败不影响其他字段
1107
- - ✅ 完全透明:无需修改业务代码
1108
-
1109
- **兼容性**:
1110
-
1111
- | BSON 版本 | mongoose 版本 | 支持状态 |
1112
- |-----------|--------------|---------|
1113
- | bson@4.x | mongoose@5.x | ✅ 完全支持 |
1114
- | bson@5.x | mongoose@6.x | ✅ 完全支持 |
1115
- | bson@6.x | mongoose@7.x | ✅ 原生支持 |
1116
-
1117
- [📖 完整文档](./docs/objectid-cross-version.md)
1118
-
1119
- ---
1120
-
1121
- ### 11. 🎯 Model 层 - 像 ORM 一样使用(v1.0.3+)
1122
-
1123
- monSQLize 提供了一个轻量级的 Model 层,让你可以像使用 ORM 一样定义数据模型,同时保持 MongoDB 的灵活性。
1124
-
1125
- > **📦 依赖说明**: Model 层基于 `schema-dsl` 库实现 Schema 验证,已随 monsqlize 自动安装。
1126
-
1127
- ```javascript
1128
- const { Model } = require('monsqlize');
1129
-
1130
- // 1. 定义 Model(集成 schema-dsl 验证)
1131
- Model.define('users', {
1132
- enums: {
1133
- role: 'admin|user|guest'
1134
- },
1135
- schema: function(dsl) {
1136
- return dsl({
1137
- username: 'string:3-32!',
1138
- email: 'email!',
1139
- role: this.enums.role.default('user'),
1140
- age: 'number:1-150'
1141
- });
1142
- },
1143
- options: {
1144
- timestamps: true, // 🆕 v1.0.3: 自动管理 createdAt/updatedAt
1145
- softDelete: true // 🆕 v1.0.3: 软删除(标记删除,支持恢复)
1146
- },
1147
- methods: (model) => ({
1148
- // 实例方法 - 注入到查询返回的文档对象
1149
- instance: {
1150
- isAdmin() {
1151
- return this.role === 'admin';
1152
- }
1153
- },
1154
- // 静态方法 - 挂载到 Model 实例
1155
- static: {
1156
- async findByEmail(email) {
1157
- return await model.findOne({ email });
1158
- }
1159
- }
1160
- }),
1161
- hooks: (model) => ({
1162
- // 生命周期钩子
1163
- insert: {
1164
- before: (ctx, docs) => {
1165
- // 自动添加时间戳
1166
- return { ...docs, createdAt: new Date() };
1167
- }
1168
- }
1169
- }),
1170
- indexes: [
1171
- { key: { username: 1 }, unique: true },
1172
- { key: { email: 1 }, unique: true }
1173
- ]
1174
- });
1175
-
1176
- // 2. 使用 Model
1177
- const db = new MonSQLize({ /* ... */ });
1178
- await db.connect();
1179
-
1180
- const User = db.model('users');
1181
-
1182
- // 自动 Schema 验证
1183
- const user = await User.insertOne({
1184
- username: 'john',
1185
- email: 'john@example.com',
1186
- age: 25
1187
- }); // ✅ 验证通过
1188
-
1189
- // 使用实例方法
1190
- const admin = await User.findOne({ username: 'admin' });
1191
- console.log(admin.isAdmin()); // true
1192
-
1193
- // 使用静态方法
1194
- const user = await User.findByEmail('john@example.com');
1195
-
1196
- // 软删除(标记删除,可恢复)
1197
- await User.deleteOne({ _id: user._id });
1198
-
1199
- // 查询(自动过滤已删除)
1200
- const users = await User.find({}); // 不包含已删除用户
1201
-
1202
- // 查询包含已删除
1203
- const allUsers = await User.findWithDeleted({});
1204
-
1205
- // 恢复已删除
1206
- await User.restore({ _id: user._id });
1207
- ```
1208
-
1209
- **特性**:
1210
- - ✅ Schema 验证(集成 schema-dsl)
1211
- - ✅ 自定义方法(instance + static)
1212
- - ✅ 生命周期钩子(before/after)
1213
- - ✅ 索引自动创建
1214
- - ✅ 自动时间戳(v1.0.3+)
1215
- - ✅ 软删除(v1.0.3+)
1216
- - ✅ 乐观锁版本控制(v1.0.3+)
1217
- - ✅ **关系定义和 populate(v1.2.0+)** 🆕
1218
- - ✅ TypeScript 类型支持
1219
-
1220
- #### 关系定义和 populate(v1.2.0+)🆕
1221
-
1222
- 轻松处理集合之间的关联关系,支持 one-to-one 和 one-to-many。
1223
-
1224
- ```javascript
1225
- // 1. 定义关系
1226
- Model.define('users', {
1227
- schema: (dsl) => dsl({
1228
- username: 'string!',
1229
- profileId: 'objectId'
1230
- }),
1231
- relations: {
1232
- // one-to-one: 用户 → 个人资料
1233
- profile: {
1234
- from: 'profiles', // 集合名
1235
- localField: 'profileId', // 本地字段
1236
- foreignField: '_id', // 外部字段
1237
- single: true // 返回类型
1238
- },
1239
- // one-to-many: 用户 → 文章列表
1240
- posts: {
1241
- from: 'posts',
1242
- localField: '_id',
1243
- foreignField: 'authorId',
1244
- single: false // 返回数组
1245
- }
1246
- }
1247
- });
1248
-
1249
- // 2. 使用 populate
1250
- const user = await User.findOne({ username: 'john' })
1251
- .populate('profile') // 填充 profile
1252
- .populate('posts', { // 填充 posts
1253
- select: 'title content', // 只选择部分字段
1254
- match: { status: 'published' }, // 额外查询条件
1255
- sort: { createdAt: -1 }, // 排序
1256
- limit: 10 // 限制数量
1257
- });
1258
-
1259
- // 3. 结果
1260
- {
1261
- _id: '...',
1262
- username: 'john',
1263
- profileId: '...',
1264
- profile: { // ← 自动填充
1265
- _id: '...',
1266
- bio: 'Software Engineer',
1267
- avatar: 'https://...'
1268
- },
1269
- posts: [ // ← 自动填充
1270
- { _id: '...', title: 'Post 1', content: '...' },
1271
- { _id: '...', title: 'Post 2', content: '...' }
1272
- ]
1273
- }
1274
- ```
1275
-
1276
- **支持的查询方法**(全部 6 个):
1277
- - ✅ `find().populate()` - 批量查询
1278
- - ✅ `findOne().populate()` - 单文档查询
1279
- - ✅ `findByIds().populate()` - 批量 ID 查询
1280
- - ✅ `findOneById().populate()` - 单 ID 查询
1281
- - ✅ `findAndCount().populate()` - 带计数查询
1282
- - ✅ `findPage().populate()` - 分页查询
1283
-
1284
- **特点**:
1285
- - ✅ 极简配置(只需 4 个字段)
1286
- - ✅ 接近 MongoDB 原生(直接对应 `$lookup`)
1287
- - ✅ 批量查询优化(避免 N+1 问题)
1288
- - ✅ 支持链式调用
1289
- - ✅ 丰富的 populate 选项(select/sort/limit/skip/match)
1290
-
1291
- [📖 Relations 详细文档](./docs/model/relations.md)
1292
-
1293
- **注意**:需要安装 `schema-dsl` 依赖:
1294
- ```bash
1295
- npm install schema-dsl
1296
- ```
1297
-
1298
- #### 热重载支持(v1.1.7+)🆕
1299
-
1300
- 在开发模式下,无需重启进程即可更新 Model 定义。
1301
-
1302
- ```javascript
1303
- const { Model } = require('monsqlize');
1304
-
1305
- // 注销 Model 定义(返回 boolean)
1306
- Model.undefine('users'); // true — 成功注销
1307
- Model.undefine('nonexistent'); // false — 不存在时不抛错
1308
-
1309
- // 替换 Model 定义(undefine + define 的组合)
1310
- Model.redefine('users', {
1311
- schema: (dsl) => dsl({ username: 'string!', email: 'email!' })
1312
- });
1313
-
1314
- // 批量热重载(重新加载所有 model 文件)
1315
- await msq._loadModels({ reload: true });
1316
- ```
1317
-
1318
- **注意事项**:
1319
- - `redefine()` 若新定义校验失败,旧定义**已被移除**(不会回滚),调用方需 try/catch
1320
- - 已实例化的 `ModelInstance` 不受影响,热重载后应通过 `db.model()` 重新获取实例
1321
-
1322
- [📖 Model 层详细文档](./docs/model.md)
1323
-
1324
- ---
1325
-
1326
- ## � 进阶功能
1327
-
1328
- ### 1. Change Streams - 实时监听数据变更 ⭐
1329
-
1330
- ```javascript
1331
- // 实时监听订单变化
1332
- const watcher = orders.watch([
1333
- { $match: { 'fullDocument.status': 'pending' } }
1334
- ]);
1335
-
1336
- watcher.on('change', (change) => {
1337
- console.log('新订单:', change.fullDocument);
1338
- // 触发通知、更新统计、失效缓存等
1339
- });
1340
-
1341
- // ✅ 自动处理:重连、错误恢复、缓存失效
1342
- ```
1343
-
1344
- **特性**: 支持聚合管道过滤 · 断点续传 · 自动失效相关缓存
1345
-
1346
- [📖 完整文档](./docs/watch.md) | [示例代码](./examples/watch.examples.js)
1347
-
1348
- ---
1349
-
1350
- ### 2. Count 队列控制 - 高并发优化 ⭐
1351
-
1352
- ```javascript
1353
- // 高并发场景:100 个用户同时请求分页
1354
- const db = new MonSQLize({
1355
- countQueue: {
1356
- enabled: true, // 默认启用
1357
- concurrency: 8 // 同时最多 8 个 count
1358
- }
1359
- });
1360
-
1361
- // ✅ 自动队列控制,防止 count 拖垮数据库
1362
- const result = await users.findPage({
1363
- query: { status: 'active' },
1364
- totals: { mode: 'async' } // 自动应用队列
1365
- });
1366
- ```
1367
-
1368
- **效果**: 数据库 CPU 从 100% → 30% · 其他查询不再超时
1369
-
1370
- [📖 完整文档](./docs/count-queue.md)
1371
-
1372
- ---
1373
-
1374
- ### 3. 链式调用 API - 优雅的查询构建 ⭐
1375
-
1376
- ```javascript
1377
- // jQuery 风格的链式调用
1378
- const result = await users
1379
- .find()
1380
- .filter({ age: { $gte: 18 } })
1381
- .sort({ createdAt: -1 })
1382
- .limit(10)
1383
- .cache(60000)
1384
- .exec();
1385
-
1386
- // ✅ 代码更清晰、可读性更强
1387
- ```
1388
-
1389
- [📖 完整文档](./docs/chaining-api.md) | [链式方法参考](./docs/chaining-methods.md)
1390
-
1391
- ---
1392
-
1393
- ### 4. Model 层乐观锁 - 防止并发修改冲突
1394
-
1395
- ```javascript
1396
- // 启用版本控制
1397
- Model.define('products', {
1398
- schema: (dsl) => dsl({ name: 'string!', stock: 'number!' }),
1399
- options: { optimisticLock: true }
1400
- });
1401
-
1402
- // 自动版本检查和更新
1403
- await Product.updateOne(
1404
- { _id: productId, __v: 1 }, // 要求版本为 1
1405
- { $inc: { stock: -1 }, $inc: { __v: 1 } } // 自动递增版本
1406
- );
1407
- // ❌ 如果版本不匹配(被其他请求修改),更新失败
1408
- ```
1409
-
1410
- [📖 Model 层文档](./docs/model.md)
1411
-
1412
- ---
1413
-
1414
- ### 5. ES Module 支持 - 现代 JavaScript
1415
-
1416
- ```javascript
1417
- // ✅ 支持 import/export
1418
- import MonSQLize from 'monsqlize';
1419
-
1420
- const db = new MonSQLize({ /* ... */ });
1421
- await db.connect();
1422
-
1423
- // 🎯 完美支持 TypeScript
1424
- import type { Collection, MonSQLizeConfig } from 'monsqlize';
1425
- ```
1426
-
1427
- [📖 ESM 文档](./docs/esm-support.md)
1428
-
1429
- ---
1430
-
1431
- ## �📊 性能测试报告
1432
-
1433
- ### 测试环境
1434
-
1435
- - **CPU**: Intel i7-9700K
1436
- - **内存**: 16GB
1437
- - **数据库**: MongoDB 5.0
1438
- - **数据量**: 100 万条
1439
-
1440
- ### 查询性能对比
1441
-
1442
- | 场景 | 原生驱动 | monSQLize (缓存) | 提升倍数 |
1443
- |------|---------|------------------|---------|
1444
- | 热点查询 (findOne) | 10ms | 0.1ms | **100x** ⚡ |
1445
- | 列表查询 (find) | 50ms | 0.5ms | **100x** ⚡ |
1446
- | 复杂聚合 (aggregate) | 200ms | 2ms | **100x** ⚡ |
1447
- | 批量插入 (10万条) | 30s | 1.2s | **25x** ⚡ |
1448
-
1449
- ### 缓存命中率
1450
-
1451
- - **电商场景**: 85% (商品/用户查询)
1452
- - **内容平台**: 75% (文章/评论查询)
1453
- - **社交应用**: 80% (个人资料/动态)
1454
-
1455
- **结论**: 在真实业务场景中,缓存命中率通常在 **70~90%**,性能提升 **10~100 倍**。
1456
-
1457
- ---
1458
-
1459
- ## 🎨 完整功能清单
1460
-
1461
- <table>
1462
- <tr>
1463
- <td width="33%">
1464
-
1465
- ### 📦 MongoDB 原生功能
1466
-
1467
- ✅ **CRUD 操作**
1468
- - [find](./docs/find.md) / [findOne](./docs/findOne.md)
1469
- - [insertOne](./docs/insert-one.md) / [insertMany](./docs/insert-many.md)
1470
- - [updateOne](./docs/update-one.md) / [updateMany](./docs/update-many.md) ⭐ (支持聚合管道 v1.0.8+)
1471
- - [deleteOne](./docs/delete-one.md) / [deleteMany](./docs/delete-many.md)
1472
- - [replaceOne](./docs/replace-one.md)
1473
- - [findOneAndUpdate](./docs/find-one-and-update.md)
1474
- - [findOneAndReplace](./docs/find-one-and-replace.md)
1475
- - [findOneAndDelete](./docs/find-one-and-delete.md)
1476
-
1477
- ✅ **聚合 & 查询**
1478
- - [aggregate](./docs/aggregate.md)
1479
- - [count](./docs/count.md) / [distinct](./docs/distinct.md)
1480
- - [watch (Change Streams)](./docs/watch.md)
1481
- - [explain](./docs/explain.md)
1482
-
1483
- ✅ **索引管理**
1484
- - createIndex / createIndexes
1485
- - listIndexes
1486
- - dropIndex / dropIndexes
1487
-
1488
- ✅ **[事务支持](./docs/transaction.md)**
1489
- - withTransaction
1490
- - startTransaction
1491
-
1492
- </td>
1493
- <td width="33%">
1494
-
1495
- ### 🚀 增强功能
1496
-
1497
- ✅ **[企业级多连接池](./docs/multi-pool.md)** (v1.0.8+)
1498
- - ConnectionPoolManager
1499
- - 5种智能选择策略
1500
- - 实时健康检查
1501
- - 自动故障转移
1502
- - 完整统计收集
1503
-
1504
- ✅ **[Saga 分布式事务](./docs/saga-transaction.md)** (v1.1.0 计划)
1505
- - 跨服务事务(设计完成)
1506
- - 自动补偿机制(设计完成)
1507
- - 状态跟踪(设计完成)
1508
- - 超时和重试(设计完成)
1509
-
1510
- ✅ **[智能缓存](./docs/cache.md)**
1511
- - TTL 过期策略
1512
- - LRU 淘汰策略
1513
- - 自动失效机制
1514
- - 并发去重
1515
- - [多层缓存 (内存+Redis)](./docs/cache-implementation.md)
1516
-
1517
- ✅ **便利方法**
1518
- - [findOneById](./docs/find-one-by-id.md)
1519
- - [findByIds](./docs/find-by-ids.md)
1520
- - [upsertOne](./docs/upsert-one.md)
1521
- - [incrementOne](./docs/increment-one.md)
1522
- - [findAndCount](./docs/find-and-count.md)
1523
-
1524
- ✅ **性能优化**
1525
- - [insertBatch](./docs/insertBatch.md) - 批量插入优化
1526
- - [deleteBatch](./docs/deleteBatch.md) - 批量删除(流式+进度监控)
1527
- - [updateBatch](./docs/updateBatch.md) - 批量更新(流式+进度监控)
1528
- - 只读事务优化
1529
- - [Count 队列控制](./docs/count-queue.md)
1530
- - 连接池管理
1531
-
1532
- ✅ **[分布式支持](./docs/distributed-deployment.md)**
1533
- - Redis 广播缓存失效
1534
- - [分布式锁](./docs/business-lock.md)
1535
- - 多实例一致性
1536
-
1537
- </td>
1538
- <td width="33%">
1539
-
1540
- ### 🛠️ 企业级特性
1541
-
1542
- ✅ **运维监控**
1543
- - [慢查询日志](./docs/slow-query-log.md)(支持持久化存储)🆕
1544
- - 性能指标统计
1545
- - 健康检查
1546
- - 缓存命中率监控
1547
-
1548
- ✅ **[深度分页](./docs/findPage.md)**
1549
- - 游标分页
1550
- - 异步总数统计
1551
- - [书签管理](./docs/bookmarks.md)
1552
- - 跳页优化
1553
-
1554
- ✅ **数据库管理**
1555
- - 跨库访问
1556
- - [Schema 验证](./docs/model.md)
1557
- - [集合管理](./docs/collection-management.md)
1558
- - 数据库命令
1559
-
1560
- ✅ **开发体验**
1561
- - TypeScript 支持
1562
- - [链式调用 API](./docs/chaining-api.md) ⭐
1563
- - ESM/CommonJS 双模式
1564
- - [ObjectId 自动转换](./docs/objectid-auto-convert.md) ⭐
1565
- - 77% 测试覆盖率
1566
-
1567
- </td>
1568
- </tr>
1569
- </table>
1570
-
1571
- ---
1572
-
1573
- ## 🆚 与 MongoDB 原生驱动对比
1574
-
1575
- <table>
1576
- <tr>
1577
- <th width="25%">特性</th>
1578
- <th width="25%">MongoDB 原生</th>
1579
- <th width="50%"><strong>monSQLize</strong></th>
1580
- </tr>
1581
- <tr>
1582
- <td><strong>API 兼容性</strong></td>
1583
- <td>✅ 原生</td>
1584
- <td>✅ 100% 兼容原生,无需学习新 API</td>
1585
- </tr>
1586
- <tr>
1587
- <td><strong>智能缓存</strong></td>
1588
- <td>❌ 需要自己实现</td>
1589
- <td>✅ 内置 TTL/LRU,开箱即用,10~100倍提升</td>
1590
- </tr>
1591
- <tr>
1592
- <td><strong>性能</strong></td>
1593
- <td>⭐⭐⭐ 基准性能</td>
1594
- <td>⭐⭐⭐⭐⭐ 缓存命中时性能提升 10~100 倍</td>
1595
- </tr>
1596
- <tr>
1597
- <td><strong>事务支持</strong></td>
1598
- <td>⭐⭐ 需要手动管理</td>
1599
- <td>⭐⭐⭐⭐⭐ 自动管理生命周期,优化只读操作</td>
1600
- </tr>
1601
- <tr>
1602
- <td><strong>分布式部署</strong></td>
1603
- <td>❌ 缓存不一致</td>
1604
- <td>✅ Redis 广播自动同步,保证一致性</td>
1605
- </tr>
1606
- <tr>
1607
- <td><strong>便利方法</strong></td>
1608
- <td>❌ 需要自己封装</td>
1609
- <td>✅ findOneById、findByIds、upsertOne 等</td>
1610
- </tr>
1611
- <tr>
1612
- <td><strong>运维监控</strong></td>
1613
- <td>⚠️ 需要额外配置</td>
1614
- <td>✅ 慢查询日志、性能统计,开箱即用</td>
1615
- </tr>
1616
- <tr>
1617
- <td><strong>学习成本</strong></td>
1618
- <td>⭐⭐⭐ MongoDB 语法</td>
1619
- <td>⭐ 零学习成本,API 完全一致</td>
1620
- </tr>
1621
- <tr>
1622
- <td><strong>迁移成本</strong></td>
1623
- <td>-</td>
1624
- <td>⭐ 只需修改初始化代码,业务代码不变</td>
1625
- </tr>
1626
- </table>
1627
-
1628
- ### 📌 何时选择 monSQLize
1629
-
1630
- ✅ **适合场景**:
1631
- - 高并发读取场景(商品详情、用户信息)
1632
- - 需要缓存但不想自己实现
1633
- - 多实例部署需要缓存一致性
1634
- - 希望零学习成本提升性能
1635
-
1636
- ⚠️ **不适合场景**:
1637
- - 纯写入应用(缓存作用有限)
1638
- - 实时性要求极高(每次必查最新)
1639
- - 简单应用,流量不大(原生驱动足够)
1640
-
1641
- ---
1642
-
1643
- ## 🚀 快速迁移指南
1644
-
1645
- ### 从 MongoDB 原生驱动迁移
1646
-
1647
- ```javascript
1648
- // ❌ 原来的代码
1649
- const { MongoClient } = require('mongodb');
1650
- const client = await MongoClient.connect('mongodb://localhost:27017');
1651
- const db = client.db('mydb');
1652
- const users = db.collection('users');
1653
-
1654
- // ✅ 迁移后的代码(只需改 3 行)
1655
- const MonSQLize = require('monsqlize'); // 1. 引入 monSQLize
1656
- const db = new MonSQLize({ // 2. 修改初始化
1657
- type: 'mongodb',
1658
- config: { uri: 'mongodb://localhost:27017/mydb' },
1659
- cache: { enabled: true } // 3. 启用缓存
1660
- });
1661
- await db.connect();
1662
- const users = db.collection('users');
1663
-
1664
- // 🎉 后续所有代码不需要改动,性能提升 10~100 倍!
1665
- const user = await users.findOne({ email }); // 完全一样的 API
1666
- ```
1667
-
1668
- ### 渐进式迁移
1669
-
1670
- ```javascript
1671
- // ✅ 可以混用原生驱动和 monSQLize
1672
- const nativeClient = await MongoClient.connect('...');
1673
- const monsqlize = new MonSQLize({ cache: { enabled: true } });
1674
-
1675
- // 性能敏感的查询用 monSQLize(启用缓存)
1676
- const hotData = await monsqlize.collection('products').find({}, { cache: 60000 });
1677
-
1678
- // 简单查询用原生驱动
1679
- const coldData = await nativeClient.db('mydb').collection('logs').find({});
1680
- ```
1681
-
1682
- ---
1683
-
1684
- ## 📖 完整文档
1685
-
1686
- ### 核心文档
1687
-
1688
- - 📖 [完整 API 文档索引](./docs/INDEX.md)
1689
- - 📖 [MongoDB 原生 vs monSQLize 对比](./docs/mongodb-native-vs-extensions.md)
1690
- - 📖 [事务使用指南](./docs/transaction.md)
1691
- - 📖 [业务级分布式锁](./docs/business-lock.md) 🆕 v1.4.0
1692
- - 📖 [SSH隧道使用指南](./docs/ssh-tunnel.md) 🆕 v1.3+
1693
- - 📖 [分布式部署指南](./docs/distributed-deployment.md)
1694
- - 📖 [性能优化指南](./docs/transaction-optimizations.md)
1695
-
1696
- ### 功能文档
1697
-
1698
- **CRUD 操作**:
1699
- - [find](./docs/find.md) | [findOne](./docs/findOne.md) | [findPage](./docs/findPage.md)
1700
- - [insertOne](./docs/insert-one.md) | [insertMany](./docs/insert-many.md) | [insertBatch](./docs/insertBatch.md)
1701
- - [updateOne](./docs/update-one.md) | [updateMany](./docs/update-many.md) | [updateBatch](./docs/updateBatch.md) | [replaceOne](./docs/replace-one.md)
1702
- - [deleteOne](./docs/delete-one.md) | [deleteMany](./docs/delete-many.md) | [deleteBatch](./docs/deleteBatch.md)
1703
-
1704
- **Model 层**:
1705
- - [Model API 文档](./docs/model.md) - Schema 验证、自定义方法、生命周期钩子
1706
-
1707
- **便利方法**:
1708
- - [findOneById](./docs/find-one-by-id.md) | [findByIds](./docs/find-by-ids.md)
1709
- - [upsertOne](./docs/upsert-one.md) | [incrementOne](./docs/increment-one.md) | [findAndCount](./docs/find-and-count.md)
1710
-
1711
- **其他功能**:
1712
- - [索引管理](./docs/create-index.md) | [聚合查询](./docs/aggregate.md)
1713
- - [缓存系统](./docs/cache.md) | [链式调用](./docs/chaining-api.md)
1714
-
1715
- ### 示例代码
1716
-
1717
- - 📁 [完整示例代码目录](./examples/) - 50+ 可运行示例
1718
-
1719
- ---
1720
-
1721
- ## 🌍 兼容性
1722
-
1723
- | 环境 | 支持版本 |
1724
- |------|---------|
1725
- | **Node.js** | 16.x, 18.x, 20.x, 21.x |
1726
- | **MongoDB** | 4.4+, 5.x, 6.x, 7.x |
1727
- | **MongoDB Driver** | 4.x, 5.x, 6.x, 7.x |
1728
- | **模块系统** | CommonJS, ESM |
1729
-
1730
- [查看完整兼容性矩阵](./docs/COMPATIBILITY.md)
1731
-
1732
- ---
1733
-
1734
- ## 🗺️ 产品路线图
1735
-
1736
- ### ✅ v1.4 (当前版本)
1737
-
1738
- - ✅ 业务级分布式锁
1739
- - ✅ 智能缓存系统
1740
- - ✅ 事务优化
1741
- - ✅ 便利方法
1742
- - ✅ 分布式支持
1743
- - ✅ Model 层(v1.0.3)- Schema 验证、自定义方法、生命周期钩子
1744
-
1745
- ### 🚧 v1.5 (计划中)
1746
-
1747
- - 🔄 查询分析器
1748
- - 🔄 自动索引建议
1749
- - 🔄 数据迁移工具
1750
- - 🔄 GraphQL 支持
1751
- - 🔄 Model 关系(relations)完善
1752
-
1753
- ### 🔮 v2.0 (未来)
1754
-
1755
- - 🔮 统一 API 支持 MySQL
1756
- - 🔮 统一 API 支持 PostgreSQL
1757
- - 🔮 完整 ORM 功能
1758
- - 🔮 数据同步中间件
1759
-
1760
- ---
1761
-
1762
- ## 🤝 贡献指南
1763
-
1764
- 我们欢迎所有形式的贡献!
1765
-
1766
- - 🐛 [提交 Bug](https://github.com/vextjs/monSQLize/issues)
1767
- - 💡 [提出新功能](https://github.com/vextjs/monSQLize/issues)
1768
- - 📖 [改进文档](https://github.com/vextjs/monSQLize/pulls)
1769
- - 💻 [提交代码](https://github.com/vextjs/monSQLize/pulls)
1770
-
1771
- ### 开发
1772
-
1773
- ```bash
1774
- # 克隆仓库
1775
- git clone https://github.com/vextjs/monSQLize.git
1776
- cd monSQLize
1777
-
1778
- # 安装依赖
1779
- npm install
1780
-
1781
- # 运行测试
1782
- npm test
1783
-
1784
- # 运行基准测试
1785
- npm run benchmark
1786
- ```
1787
-
1788
- ---
1789
-
1790
- ## 📄 许可证
1791
-
1792
- [MIT License](./LICENSE)
1793
-
1794
- ---
1795
-
1796
- ## 💬 社区与支持
1797
-
1798
- - 📧 **Email**: support@monsqlize.dev
1799
- - 💬 **Issues**: [GitHub Issues](https://github.com/vextjs/monSQLize/issues)
1800
- - 📖 **文档**: [完整文档](./docs/INDEX.md)
1801
- - 🌟 **Star**: 如果觉得有用,请给我们一个 Star ⭐
1802
-
1803
- ---
1804
-
1805
- ## 🎉 快速链接
1806
-
1807
- <div align="center">
1808
-
1809
- **[🚀 快速开始](#-5分钟快速开始)** ·
1810
- **[📚 完整文档](./docs/INDEX.md)** ·
1811
- **[💻 示例代码](./examples/)** ·
1812
- **[🐛 报告问题](https://github.com/vextjs/monSQLize/issues)** ·
1813
- **[⭐ Star 项目](https://github.com/vextjs/monSQLize)**
1814
-
1815
- ---
1816
-
1817
- ### 让 MongoDB 快 10~100 倍,从现在开始 🚀
1818
-
1819
- ```bash
1820
- npm install monsqlize
1821
- ```
1822
-
1823
- ---
1824
-
1825
- Made with ❤️ by monSQLize Team
1826
-
1827
- </div>
1828
-
1
+ # monSQLize
2
+
3
+ TypeScript-native MongoDB ODM and enhancement layer with v1-compatible APIs, multi-level caching, distributed locks, transactions, Saga orchestration, model validation, connection pools, Change Stream sync, slow-query logging, and CommonJS / ESM / TypeScript declaration outputs.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/monsqlize.svg)](https://www.npmjs.com/package/monsqlize)
6
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
7
+ [![MongoDB](https://img.shields.io/badge/MongoDB-6.x%20%2F%207.x-green.svg)](https://www.mongodb.com/)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-18%2B-brightgreen)](https://nodejs.org/)
9
+
10
+ ```bash
11
+ npm install monsqlize
12
+ ```
13
+
14
+ monSQLize is currently a MongoDB-focused package. The long-term product direction is to keep the MongoDB-style query experience while gradually extending the same high-level API shape to additional database backends.
15
+
16
+ ## Table of Contents
17
+
18
+ - [Why monSQLize](#why-monsqlize)
19
+ - [When to Use It](#when-to-use-it)
20
+ - [Installation](#installation)
21
+ - [Quick Start](#quick-start)
22
+ - [Model Layer](#model-layer)
23
+ - [Caching and Performance](#caching-and-performance)
24
+ - [Advanced Capabilities](#advanced-capabilities)
25
+ - [Migration from the MongoDB Driver](#migration-from-the-mongodb-driver)
26
+ - [Compatibility](#compatibility)
27
+ - [Documentation](#documentation)
28
+ - [Development](#development)
29
+ - [Release Status](#release-status)
30
+ - [Roadmap](#roadmap)
31
+ - [License](#license)
32
+ - [Support](#support)
33
+
34
+ ## Why monSQLize
35
+
36
+ monSQLize keeps the MongoDB driver mental model while adding the production features most teams end up building around it:
37
+
38
+ - Drop-in collection helpers that preserve MongoDB-style CRUD, aggregation, indexes, transactions, and Change Streams.
39
+ - Smart caching through `cache-hub`, including local memory caching, optional Redis-backed L2 caching, automatic invalidation, and function-level caching.
40
+ - A lightweight Model layer with `schema-dsl` validation, hooks, relations, populate, custom methods, timestamps, soft delete, and optimistic locking.
41
+ - Multi-connection-pool support, pool health checks, pool-scoped collections/models, and fallback strategies.
42
+ - Business locks and distributed locks for multi-instance deployments.
43
+ - Saga orchestration for multi-step business workflows.
44
+ - Change Stream sync helpers with resume token storage.
45
+ - Slow-query logging and query diagnostics.
46
+ - CommonJS, ESM, and TypeScript declaration outputs from `dist/**`.
47
+
48
+ ## When to Use It
49
+
50
+ monSQLize is a good fit when you need:
51
+
52
+ | Scenario | Benefit |
53
+ |---|---|
54
+ | High-concurrency reads | Cache hot data and reduce repeated database work. |
55
+ | MongoDB API compatibility | Keep familiar query syntax while adding higher-level helpers. |
56
+ | Multi-instance services | Use Redis invalidation and distributed locks to keep instances coordinated. |
57
+ | Transaction-heavy flows | Use `withTransaction()` and transaction-aware helpers instead of hand-rolled lifecycle code. |
58
+ | Model-level ergonomics | Add schema validation, hooks, populate, and custom methods only where needed. |
59
+ | Smooth upgrade from v1 | Keep legacy application source stable while adopting the TypeScript rewrite. |
60
+
61
+ monSQLize is usually not the best first choice for pure write-heavy workloads, extremely strict real-time reads where every query must bypass cache, or very small applications that do not need the extra operational layer.
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ npm install monsqlize
67
+ ```
68
+
69
+ Runtime dependencies installed with the package:
70
+
71
+ - `mongodb` - official MongoDB driver.
72
+ - `schema-dsl` - model schema validation runtime dependency.
73
+ - `cache-hub` - cache and function-cache foundation.
74
+ - `async-lock` - local concurrency lock support.
75
+
76
+ Optional dependencies:
77
+
78
+ - `ioredis` - required only when you enable Redis / L2 cache features.
79
+ - `ssh2` - required only when you connect through an SSH tunnel.
80
+
81
+ ```bash
82
+ npm install ioredis ssh2
83
+ ```
84
+
85
+ ## Quick Start
86
+
87
+ ### CommonJS
88
+
89
+ ```js
90
+ const MonSQLize = require('monsqlize');
91
+
92
+ const db = new MonSQLize({
93
+ type: 'mongodb',
94
+ databaseName: 'mydb',
95
+ config: {
96
+ uri: 'mongodb://localhost:27017'
97
+ },
98
+ cache: {
99
+ enabled: true,
100
+ ttl: 60_000
101
+ }
102
+ });
103
+
104
+ await db.connect();
105
+
106
+ const users = db.collection('users');
107
+
108
+ await users.insertOne({
109
+ username: 'john',
110
+ email: 'john@example.com',
111
+ createdAt: new Date()
112
+ });
113
+
114
+ const user = await users.findOne({ email: 'john@example.com' });
115
+ const userById = await users.findOneById('507f1f77bcf86cd799439011');
116
+
117
+ await users.updateOne(
118
+ { email: 'john@example.com' },
119
+ { $set: { lastLoginAt: new Date() } }
120
+ );
121
+
122
+ await db.close();
123
+ ```
124
+
125
+ ### ESM and TypeScript
126
+
127
+ ```ts
128
+ import MonSQLize from 'monsqlize';
129
+ import type { Collection } from 'monsqlize';
130
+
131
+ const db = new MonSQLize({
132
+ type: 'mongodb',
133
+ databaseName: 'mydb',
134
+ config: {
135
+ uri: 'mongodb://localhost:27017'
136
+ }
137
+ });
138
+
139
+ await db.connect();
140
+
141
+ const users: Collection = db.collection('users');
142
+ const activeUsers = await users.find({ status: 'active' }).toArray();
143
+
144
+ await db.close();
145
+ ```
146
+
147
+ Published entry points:
148
+
149
+ | Format | Entry |
150
+ |---|---|
151
+ | CommonJS | `dist/cjs/index.cjs` |
152
+ | ESM | `dist/esm/index.mjs` |
153
+ | Types | `dist/types/index.d.ts` |
154
+
155
+ The package root exports only the public package contract. Deep imports into historical `lib/**` files are not part of the v2 publishing surface.
156
+
157
+ ## Model Layer
158
+
159
+ The Model layer is optional. Use it when you want schema validation, hooks, relations, populate, custom methods, timestamps, soft delete, or optimistic locking.
160
+
161
+ `schema-dsl` is installed automatically as a runtime dependency of monSQLize. You only need to declare `schema-dsl` in your own app if your application imports it directly.
162
+
163
+ ### Manual Model Registration
164
+
165
+ ```js
166
+ const MonSQLize = require('monsqlize');
167
+ const { Model } = MonSQLize;
168
+
169
+ Model.define('users', {
170
+ schema: (dsl) => dsl({
171
+ username: 'string:3-32!',
172
+ email: 'email!',
173
+ password: 'string:6-!',
174
+ age: 'number:0-120'
175
+ }),
176
+ relations: {
177
+ posts: {
178
+ from: 'posts',
179
+ localField: '_id',
180
+ foreignField: 'userId',
181
+ single: false
182
+ }
183
+ },
184
+ hooks: (model) => ({
185
+ insert: {
186
+ before: async (ctx, doc) => {
187
+ doc.createdAt = new Date();
188
+ return doc;
189
+ }
190
+ }
191
+ }),
192
+ methods: (model) => ({
193
+ instance: {
194
+ checkPassword(password) {
195
+ return this.password === password;
196
+ }
197
+ },
198
+ static: {
199
+ async findByUsername(username) {
200
+ return model.findOne({ username });
201
+ }
202
+ }
203
+ })
204
+ });
205
+
206
+ const db = new MonSQLize({
207
+ type: 'mongodb',
208
+ databaseName: 'mydb',
209
+ config: { uri: 'mongodb://localhost:27017' }
210
+ });
211
+
212
+ await db.connect();
213
+
214
+ const User = db.model('users');
215
+ const user = await User.insertOne({
216
+ username: 'john',
217
+ email: 'john@example.com',
218
+ password: 'secret123',
219
+ age: 25
220
+ });
221
+ ```
222
+
223
+ ### Automatic Model Loading
224
+
225
+ ```js
226
+ const path = require('path');
227
+ const MonSQLize = require('monsqlize');
228
+
229
+ const db = new MonSQLize({
230
+ type: 'mongodb',
231
+ databaseName: 'mydb',
232
+ config: { uri: 'mongodb://localhost:27017' },
233
+ models: path.join(__dirname, 'models')
234
+ });
235
+
236
+ await db.connect();
237
+
238
+ const User = db.model('users');
239
+ ```
240
+
241
+ ```js
242
+ // models/user.model.js
243
+ module.exports = {
244
+ name: 'users',
245
+ schema: (dsl) => dsl({
246
+ username: 'string:3-32!',
247
+ email: 'email!'
248
+ }),
249
+ methods: (model) => ({
250
+ static: {
251
+ async findByUsername(username) {
252
+ return model.findOne({ username });
253
+ }
254
+ }
255
+ })
256
+ };
257
+ ```
258
+
259
+ Relative model paths are resolved from `process.cwd()`. In production services, prefer absolute paths such as `path.join(__dirname, 'models')`.
260
+
261
+ ### Populate
262
+
263
+ ```js
264
+ Model.define('posts', {
265
+ schema: (dsl) => dsl({
266
+ title: 'string:1-200!',
267
+ content: 'string!',
268
+ userId: 'objectId!'
269
+ })
270
+ });
271
+
272
+ const userWithPosts = await User.findOne({ username: 'john' })
273
+ .populate('posts', {
274
+ select: 'title content',
275
+ match: { status: 'published' },
276
+ sort: { createdAt: -1 },
277
+ limit: 10
278
+ });
279
+ ```
280
+
281
+ Populate is supported by `find()`, `findOne()`, `findByIds()`, `findOneById()`, `findAndCount()`, and `findPage()`.
282
+
283
+ ## Caching and Performance
284
+
285
+ monSQLize can cache collection queries and arbitrary async functions.
286
+
287
+ ```js
288
+ const users = db.collection('users');
289
+
290
+ const hotUser = await users.findOne(
291
+ { email: 'john@example.com' },
292
+ { cache: 60_000 }
293
+ );
294
+ ```
295
+
296
+ ```js
297
+ const { withCache } = require('monsqlize');
298
+
299
+ async function getUserProfile(userId) {
300
+ const user = await db.collection('users').findOneById(userId);
301
+ const orders = await db.collection('orders').find({ userId }).toArray();
302
+ return { user, orders };
303
+ }
304
+
305
+ const cachedGetUserProfile = withCache(getUserProfile, {
306
+ ttl: 300_000,
307
+ cache: db.getCache()
308
+ });
309
+
310
+ await cachedGetUserProfile('user-1');
311
+ ```
312
+
313
+ Cache capabilities include:
314
+
315
+ - In-memory L1 cache.
316
+ - Optional Redis-backed L2 cache.
317
+ - Automatic invalidation after writes.
318
+ - Function-level caching through `withCache()`.
319
+ - In-flight request deduplication.
320
+ - Namespaces, TTLs, statistics, and conditional caching.
321
+
322
+ ## Advanced Capabilities
323
+
324
+ ### Transactions
325
+
326
+ ```js
327
+ await db.withTransaction(async (session) => {
328
+ await db.collection('orders').insertOne({ userId, status: 'pending' }, { session });
329
+ await db.collection('users').updateOne(
330
+ { _id: userId },
331
+ { $inc: { orderCount: 1 } },
332
+ { session }
333
+ );
334
+ });
335
+ ```
336
+
337
+ ### Connection Pools
338
+
339
+ ```js
340
+ const db = new MonSQLize({
341
+ type: 'mongodb',
342
+ databaseName: 'main',
343
+ config: { uri: 'mongodb://primary:27017' },
344
+ pools: [
345
+ { name: 'analytics', uri: 'mongodb://analytics:27017' }
346
+ ]
347
+ });
348
+
349
+ const reports = db.pool('analytics').collection('reports');
350
+ ```
351
+
352
+ ### Distributed Locks
353
+
354
+ ```js
355
+ await db.withLock('inventory:sku-1', async () => {
356
+ await db.collection('inventory').updateOne(
357
+ { sku: 'sku-1' },
358
+ { $inc: { stock: -1 } }
359
+ );
360
+ });
361
+ ```
362
+
363
+ ### Change Streams
364
+
365
+ ```js
366
+ const watcher = db.collection('orders').watch([
367
+ { $match: { 'fullDocument.status': 'pending' } }
368
+ ]);
369
+
370
+ watcher.on('change', (change) => {
371
+ console.log('Order changed:', change.fullDocument);
372
+ });
373
+ ```
374
+
375
+ ### Saga Orchestration
376
+
377
+ ```js
378
+ db.defineSaga('checkout', [
379
+ {
380
+ name: 'reserveInventory',
381
+ execute: async (ctx) => reserveInventory(ctx),
382
+ compensate: async (ctx) => releaseInventory(ctx)
383
+ },
384
+ {
385
+ name: 'chargePayment',
386
+ execute: async (ctx) => chargePayment(ctx),
387
+ compensate: async (ctx) => refundPayment(ctx)
388
+ }
389
+ ]);
390
+
391
+ await db.executeSaga('checkout', { orderId });
392
+ ```
393
+
394
+ ## Migration from the MongoDB Driver
395
+
396
+ The smallest migration is usually to replace only initialization:
397
+
398
+ ```js
399
+ const { MongoClient } = require('mongodb');
400
+
401
+ const nativeClient = await MongoClient.connect('mongodb://localhost:27017');
402
+ const nativeUsers = nativeClient.db('mydb').collection('users');
403
+ ```
404
+
405
+ ```js
406
+ const MonSQLize = require('monsqlize');
407
+
408
+ const db = new MonSQLize({
409
+ type: 'mongodb',
410
+ databaseName: 'mydb',
411
+ config: { uri: 'mongodb://localhost:27017' },
412
+ cache: { enabled: true }
413
+ });
414
+
415
+ await db.connect();
416
+ const users = db.collection('users');
417
+ ```
418
+
419
+ MongoDB-style collection calls can remain unchanged in most cases:
420
+
421
+ ```js
422
+ const user = await users.findOne({ email });
423
+ const list = await users.find({ status: 'active' }).toArray();
424
+ ```
425
+
426
+ The current v2.0.0 release candidate has been validated against the workspace consumers `chat`, `payment`, `user`, `admin`, `search`, `vext`, and `permission-core` without requiring business-source changes in those projects.
427
+
428
+ ## Compatibility
429
+
430
+ | Surface | Current Support |
431
+ |---|---|
432
+ | Node.js | `>=18.0.0`; CI covers Node 18 / 20 / 22. |
433
+ | MongoDB driver | `mongodb@^6.21.0` baseline; driver 7 has additional compatibility coverage. |
434
+ | MongoDB server | Memory-server based 6.x / 7.x validation is covered by the project test matrix. |
435
+ | Module systems | CommonJS and ESM are both validated. |
436
+ | TypeScript | Public declarations are published from `dist/types/index.d.ts`. |
437
+ | Package license | Apache-2.0. |
438
+
439
+ See the current support and verification documents:
440
+
441
+ - [docs/README.md](https://github.com/vextjs/monSQLize/blob/main/docs/README.md)
442
+ - [docs/support-matrix.md](https://github.com/vextjs/monSQLize/blob/main/docs/support-matrix.md)
443
+ - [docs/verification-entrypoints.md](https://github.com/vextjs/monSQLize/blob/main/docs/verification-entrypoints.md)
444
+ - [test/compatibility/README.md](https://github.com/vextjs/monSQLize/blob/main/test/compatibility/README.md)
445
+ - [test/validation/VERIFICATION-PROGRESS.md](https://github.com/vextjs/monSQLize/blob/main/test/validation/VERIFICATION-PROGRESS.md)
446
+
447
+ ## Documentation
448
+
449
+ Current TypeScript documentation and examples are the source of truth for the v2 package:
450
+
451
+ - `docs/**` - current documentation.
452
+ - `examples/**` - TypeScript examples.
453
+ - `test/compatibility/**` - package exports and compatibility guards.
454
+ - `test/validation/**` - verification ledgers and mapping notes.
455
+
456
+ Historical v1 assets are useful for tracing old behavior, but they are not the current publishing surface for v2.
457
+
458
+ ## Development
459
+
460
+ ```bash
461
+ git clone https://github.com/vextjs/monSQLize.git
462
+ cd monSQLize
463
+ npm install
464
+ ```
465
+
466
+ Common commands:
467
+
468
+ ```bash
469
+ npm run build
470
+ npm run type-check
471
+ npm test
472
+ npm run verify:fast
473
+ npm run release:preflight
474
+ ```
475
+
476
+ Release preflight runs linting, type checks, size guards, runtime checks, compatibility checks, refactor guards, the default test suite, and `npm pack --dry-run`.
477
+
478
+ `npm run release:publish` runs the preflight gate once and then calls `npm publish --ignore-scripts` so the final publish step does not repeat the full lifecycle gate. Raw `npm publish` is still guarded by `prepublishOnly`.
479
+
480
+ Optional commands:
481
+
482
+ ```bash
483
+ npm run test:examples
484
+ npm run test:coverage
485
+ npm run test:server-matrix
486
+ npm run test:real-env:private
487
+ ```
488
+
489
+ `test:real-env:private` is intentionally opt-in and expects private environment variables. It is not part of the default CI or release gate.
490
+
491
+ ## Release Status
492
+
493
+ The current release candidate is `v2.0.0`.
494
+
495
+ Key release-readiness points:
496
+
497
+ - TypeScript rewrite completed for the current runtime and test entry points.
498
+ - Package exports are consolidated under `dist/cjs`, `dist/esm`, and `dist/types`.
499
+ - npm packages include the runtime bundles and declaration files only; source maps are disabled by default and can be generated locally with `MONSQLIZE_BUILD_SOURCEMAPS=1 npm run build`.
500
+ - v1 smooth-upgrade compatibility has been validated against the target workspace consumers.
501
+ - `schema-dsl` follows the npm `latest` TypeScript line `^2.0.3`; deprecated `2.3.x` mistake releases are intentionally excluded.
502
+ - GitHub Actions publishes to npm from `v*` tags after running `npm run release:preflight`; the publish step skips duplicate lifecycle scripts because the gate already ran in the same job.
503
+
504
+ ## Roadmap
505
+
506
+ ### v2.0.0
507
+
508
+ - TypeScript-native runtime and declarations.
509
+ - v1 smooth-upgrade compatibility bridge.
510
+ - Multi-level cache and function-cache support through `cache-hub`.
511
+ - Transactions, business locks, distributed locks, Saga orchestration, connection pools, Change Stream sync, and slow-query logging.
512
+ - Model layer with `schema-dsl` validation, relations, populate, hooks, and custom methods.
513
+
514
+ ### v2.x
515
+
516
+ - Query analyzer improvements.
517
+ - Automatic index suggestions.
518
+ - Migration tooling.
519
+ - GraphQL integration experiments.
520
+ - More real-environment validation coverage.
521
+
522
+ ### v3.0+
523
+
524
+ - Unified API experiments for MySQL.
525
+ - Unified API experiments for PostgreSQL.
526
+ - Broader ORM capabilities.
527
+ - Cross-database sync middleware.
528
+
529
+ ## License
530
+
531
+ monSQLize is released under the [Apache License 2.0](./LICENSE).
532
+
533
+ ## Support
534
+
535
+ - Issues: [GitHub Issues](https://github.com/vextjs/monSQLize/issues)
536
+ - npm: [monsqlize](https://www.npmjs.com/package/monsqlize)
537
+ - Website: [https://vextjs.github.io/monSQLize/](https://vextjs.github.io/monSQLize/)