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
@@ -1,1090 +0,0 @@
1
- /**
2
- * 表达式编译器
3
- * 将统一表达式编译为目标数据库语法
4
- */
5
-
6
- const ExpressionCache = require('../cache/ExpressionCache');
7
- const { isExpressionObject } = require('../detector');
8
- const extensions = require('./ExpressionCompilerExtensions');
9
-
10
- class ExpressionCompiler {
11
- /**
12
- * @param {Object} options - 编译器配置
13
- * @param {boolean} options.debug - 是否启用调试模式
14
- * @param {Object} options.cache - 缓存配置
15
- */
16
- constructor(options = {}) {
17
- this.debug = options.debug || false;
18
- this.cache = new ExpressionCache(options.cache || {});
19
-
20
- // 绑定扩展方法到实例(v1.1.0 新增44个操作符)
21
- Object.keys(extensions).forEach(key => {
22
- this[key] = extensions[key].bind(this);
23
- });
24
- }
25
-
26
- /**
27
- * 编译表达式对象
28
- * @param {Object} exprObj - 表达式对象
29
- * @param {Object} options - 编译选项
30
- * @param {string} options.targetDB - 目标数据库,默认 'mongodb'
31
- * @returns {*} 编译后的结果
32
- */
33
- compile(exprObj, options = {}) {
34
- if (!isExpressionObject(exprObj)) {
35
- throw new Error('Invalid expression object');
36
- }
37
-
38
- const targetDB = options.targetDB || 'mongodb';
39
- const context = options.context || 'match'; // match, project, group
40
- const expression = exprObj.__expr__;
41
-
42
- // 尝试从缓存获取
43
- const cacheKey = `${context}:${expression}`;
44
- const cached = this.cache.get(cacheKey, targetDB);
45
- if (cached !== null) {
46
- if (this.debug) {
47
- console.log(`[Expression] Cache hit: ${expression}`);
48
- }
49
- return cached;
50
- }
51
-
52
- if (this.debug) {
53
- console.log(`[Expression] Compiling: ${expression} (context: ${context})`);
54
- }
55
-
56
- // 编译表达式
57
- const compiled = this._compileExpression(expression, targetDB, context);
58
-
59
- // 缓存编译结果
60
- this.cache.set(cacheKey, compiled, targetDB);
61
-
62
- return compiled;
63
- }
64
-
65
- /**
66
- * 编译表达式字符串
67
- * @param {string} expression - 表达式字符串
68
- * @param {string} targetDB - 目标数据库
69
- * @returns {*} 编译后的结果
70
- * @private
71
- */
72
- _compileExpression(expression, targetDB, context = 'match') {
73
- // 先编译内部表达式(不带$expr包装)
74
- const innerExpr = this._compileInnerExpression(expression, targetDB);
75
-
76
- // 根据上下文决定是否包装$expr
77
- if (context === 'match') {
78
- return { $expr: innerExpr };
79
- } else {
80
- // project, group, addFields 等直接返回表达式
81
- return innerExpr;
82
- }
83
- }
84
-
85
- _compileInnerExpression(expression, targetDB) {
86
- // 0. 函数调用: 所有支持的函数(122个MongoDB操作符完整支持)
87
- const funcMatch = expression.match(/^(CONCAT|UPPER|LOWER|TRIM|SUBSTR|LENGTH|ABS|CEIL|FLOOR|ROUND|SQRT|POW|SIZE|IN|SLICE|FIRST|LAST|ARRAY_ELEM_AT|FILTER|MAP|INDEX_OF|CONCAT_ARRAYS|TYPE|NOT|EXISTS|IS_NUMBER|IS_ARRAY|SUM|AVG|MAX|MIN|COUNT|PUSH|ADD_TO_SET|YEAR|MONTH|DAY_OF_MONTH|HOUR|MINUTE|SECOND|SPLIT|REPLACE|INDEX_OF_STR|LTRIM|RTRIM|SUBSTR_CP|REGEX|MERGE_OBJECTS|TO_INT|TO_STRING|OBJECT_TO_ARRAY|ARRAY_TO_OBJECT|SET_UNION|SWITCH|DATE_ADD|DATE_SUBTRACT|DATE_DIFF|DATE_TO_STRING|DATE_FROM_STRING|TO_BOOL|TO_DATE|TO_DOUBLE|CONVERT|TO_DECIMAL|TO_LONG|TO_OBJECT_ID|REDUCE|ZIP|REVERSE_ARRAY|RANGE|DATE_FROM_PARTS|DATE_TO_PARTS|ISO_WEEK|ISO_WEEK_YEAR|ISO_DAY_OF_WEEK|DAY_OF_WEEK|DAY_OF_YEAR|WEEK|STR_LEN_BYTES|STR_LEN_CP|SUBSTR_BYTES|LOG|LOG10|ALL_ELEMENTS_TRUE|ANY_ELEMENT_TRUE|COND|IF_NULL|SET_FIELD|UNSET_FIELD|GET_FIELD|SET_DIFFERENCE|SET_EQUALS|SET_INTERSECTION|SET_IS_SUBSET|LET|LITERAL|RAND|SAMPLE_RATE)\s*\((.+)?\)$/i);
88
- if (funcMatch) {
89
- const [, funcName, args] = funcMatch;
90
- const upperFuncName = funcName.toUpperCase();
91
-
92
- // 字符串函数
93
- if (['CONCAT', 'UPPER', 'LOWER', 'TRIM', 'SUBSTR', 'LENGTH'].includes(upperFuncName)) {
94
- return this._compileStringFunction(upperFuncName, args, targetDB);
95
- }
96
-
97
- // 字符串高级函数
98
- if (['SPLIT', 'REPLACE', 'INDEX_OF_STR', 'LTRIM', 'RTRIM', 'SUBSTR_CP'].includes(upperFuncName)) {
99
- return this._compileStringAdvancedFunction(upperFuncName, args, targetDB);
100
- }
101
-
102
- // 数学函数
103
- if (['ABS', 'CEIL', 'FLOOR', 'ROUND', 'SQRT', 'POW'].includes(upperFuncName)) {
104
- return this._compileMathFunction(upperFuncName, args, targetDB);
105
- }
106
-
107
- // 数组基础函数
108
- if (['SIZE', 'IN', 'SLICE', 'FIRST', 'LAST', 'ARRAY_ELEM_AT'].includes(upperFuncName)) {
109
- return this._compileArrayFunction(upperFuncName, args, targetDB);
110
- }
111
-
112
- // 数组高级函数
113
- if (['FILTER', 'MAP', 'INDEX_OF', 'CONCAT_ARRAYS'].includes(upperFuncName)) {
114
- return this._compileArrayAdvancedFunction(upperFuncName, args, targetDB);
115
- }
116
-
117
- // 聚合累加器
118
- if (['SUM', 'AVG', 'MAX', 'MIN', 'COUNT', 'PUSH', 'ADD_TO_SET'].includes(upperFuncName)) {
119
- return this._compileAggregationFunction(upperFuncName, args, targetDB);
120
- }
121
-
122
- // 日期基础函数
123
- if (['YEAR', 'MONTH', 'DAY_OF_MONTH', 'HOUR', 'MINUTE', 'SECOND'].includes(upperFuncName)) {
124
- return this._compileDateFunction(upperFuncName, args, targetDB);
125
- }
126
-
127
- // 日期高级函数(v1.1.0)
128
- if (['DATE_ADD', 'DATE_SUBTRACT', 'DATE_DIFF', 'DATE_TO_STRING', 'DATE_FROM_STRING'].includes(upperFuncName)) {
129
- return this._compileDateAdvancedFunction(upperFuncName, args, targetDB);
130
- }
131
-
132
- // 日期扩展函数(v1.1.0)
133
- if (['DATE_FROM_PARTS', 'DATE_TO_PARTS', 'ISO_WEEK', 'ISO_WEEK_YEAR', 'ISO_DAY_OF_WEEK', 'DAY_OF_WEEK', 'DAY_OF_YEAR', 'WEEK'].includes(upperFuncName)) {
134
- return this._compileDateExtendedFunction(upperFuncName, args, targetDB);
135
- }
136
-
137
- // 类型转换函数(v1.1.0)
138
- if (['TO_BOOL', 'TO_DATE', 'TO_DOUBLE', 'TO_DECIMAL', 'TO_LONG', 'TO_OBJECT_ID', 'CONVERT'].includes(upperFuncName)) {
139
- return this._compileTypeConversionFunction(upperFuncName, args, targetDB);
140
- }
141
-
142
- // 数组扩展函数(v1.1.0)
143
- if (['REDUCE', 'ZIP', 'REVERSE_ARRAY', 'RANGE'].includes(upperFuncName)) {
144
- return this._compileArrayExtendedFunction(upperFuncName, args, targetDB);
145
- }
146
-
147
- // 字符串扩展函数(v1.1.0)
148
- if (['STR_LEN_BYTES', 'STR_LEN_CP', 'SUBSTR_BYTES'].includes(upperFuncName)) {
149
- return this._compileStringExtendedFunction(upperFuncName, args, targetDB);
150
- }
151
-
152
- // 数学扩展函数(v1.1.0)
153
- if (['LOG', 'LOG10'].includes(upperFuncName)) {
154
- return this._compileMathExtendedFunction(upperFuncName, args, targetDB);
155
- }
156
-
157
- // 逻辑扩展函数(v1.1.0)
158
- if (['ALL_ELEMENTS_TRUE', 'ANY_ELEMENT_TRUE'].includes(upperFuncName)) {
159
- return this._compileLogicalExtendedFunction(upperFuncName, args, targetDB);
160
- }
161
-
162
- // 条件扩展函数(v1.1.0)
163
- if (['COND', 'IF_NULL'].includes(upperFuncName)) {
164
- return this._compileConditionalExtendedFunction(upperFuncName, args, targetDB);
165
- }
166
-
167
- // 对象操作函数(v1.1.0)
168
- if (['SET_FIELD', 'UNSET_FIELD', 'GET_FIELD'].includes(upperFuncName)) {
169
- return this._compileObjectOperationFunction(upperFuncName, args, targetDB);
170
- }
171
-
172
- // 集合操作函数(v1.1.0)
173
- if (['SET_DIFFERENCE', 'SET_EQUALS', 'SET_INTERSECTION', 'SET_IS_SUBSET'].includes(upperFuncName)) {
174
- return this._compileSetOperationFunction(upperFuncName, args, targetDB);
175
- }
176
-
177
- // 高级操作函数(v1.1.0)
178
- if (['LET', 'LITERAL', 'RAND', 'SAMPLE_RATE'].includes(upperFuncName)) {
179
- return this._compileAdvancedOperationFunction(upperFuncName, args, targetDB);
180
- }
181
-
182
- // 高频操作符
183
- if (['REGEX', 'MERGE_OBJECTS', 'TO_INT', 'TO_STRING', 'OBJECT_TO_ARRAY', 'ARRAY_TO_OBJECT', 'SET_UNION'].includes(upperFuncName)) {
184
- return this._compileHighFrequencyFunction(upperFuncName, args, targetDB);
185
- }
186
-
187
- // 条件扩展
188
- if (upperFuncName === 'SWITCH') {
189
- return this._compileSwitchFunction(args, targetDB);
190
- }
191
-
192
- // 类型/逻辑函数
193
- if (['TYPE', 'NOT', 'EXISTS', 'IS_NUMBER', 'IS_ARRAY'].includes(upperFuncName)) {
194
- return this._compileTypeFunction(upperFuncName, args, targetDB);
195
- }
196
- }
197
-
198
- // 1. 逻辑操作符: && (AND), || (OR)
199
- // ...existing code...
200
- if (expression.includes('&&')) {
201
- const parts = expression.split('&&').map(p => p.trim());
202
- const compiledParts = parts.map(part => this._compileInnerExpression(part, targetDB));
203
- return { $and: compiledParts };
204
- }
205
-
206
- if (expression.includes('||')) {
207
- const parts = expression.split('||').map(p => p.trim());
208
- const compiledParts = parts.map(part => this._compileInnerExpression(part, targetDB));
209
- return { $or: compiledParts };
210
- }
211
-
212
- // 2. 三元运算符: ? :
213
- // 注意:需要从左到右匹配,处理嵌套的三元运算符
214
- const ternaryMatch = expression.match(/^([^?]+)\s*\?\s*([^:]+)\s*:\s*(.+)$/);
215
- if (ternaryMatch) {
216
- const [, condition, thenValue, elseValue] = ternaryMatch;
217
- const compiledCondition = this._compileInnerExpression(condition.trim(), targetDB);
218
-
219
- // else部分可能包含嵌套的三元运算符,需要递归解析
220
- const parseThenElse = (val) => {
221
- const trimmed = val.trim();
222
- // 检查是否是嵌套的三元运算符
223
- if (trimmed.includes('?') && trimmed.includes(':')) {
224
- return this._compileInnerExpression(trimmed, targetDB);
225
- }
226
- return this._parseValue(trimmed);
227
- };
228
-
229
- return {
230
- $cond: {
231
- if: compiledCondition,
232
- then: parseThenElse(thenValue),
233
- else: parseThenElse(elseValue)
234
- }
235
- };
236
- }
237
-
238
- // 3. 空值合并: ??
239
- if (expression.includes('??')) {
240
- const parts = expression.split('??').map(p => p.trim());
241
- if (parts.length === 2) {
242
- return {
243
- $ifNull: [this._parseValue(parts[0]), this._parseValue(parts[1])]
244
- };
245
- }
246
- }
247
-
248
- // 4. 算术运算符(低优先级): +, -
249
- const addSubMatch = expression.match(/^(.+?)\s*([+\-])\s*(.+)$/);
250
- if (addSubMatch) {
251
- const [, left, op, right] = addSubMatch;
252
-
253
- // 排除负号
254
- if (!(op === '-' && left.trim() === '')) {
255
- const operatorMap = { '+': '$add', '-': '$subtract' };
256
- return {
257
- [operatorMap[op]]: [this._parseOperand(left, targetDB), this._parseOperand(right, targetDB)]
258
- };
259
- }
260
- }
261
-
262
- // 5. 算术运算符(高优先级): *, /, %
263
- const mulDivMatch = expression.match(/^(.+?)\s*([*/%])\s*(.+)$/);
264
- if (mulDivMatch) {
265
- const [, left, op, right] = mulDivMatch;
266
- const operatorMap = { '*': '$multiply', '/': '$divide', '%': '$mod' };
267
-
268
- return {
269
- [operatorMap[op]]: [this._parseOperand(left, targetDB), this._parseOperand(right, targetDB)]
270
- };
271
- }
272
-
273
- // 6. 比较操作符
274
- // 先检查比较链(连续比较运算符)
275
- const comparisonChainMatch = expression.match(/\b\w+\s*(===|!==|>=|<=|>|<)\s+\w+\s+(===|!==|>=|<=|>|<)/);
276
- if (comparisonChainMatch) {
277
- throw new Error(`Invalid comparison chain: ${expression}. Use && to combine comparisons (e.g., "a > b && b > c").`);
278
- }
279
-
280
- // 支持字段名或函数调用
281
- const comparisonMatch = expression.match(/^(.+?)\s*(===|!==|>=|<=|>|<)\s*(.+)$/);
282
- if (comparisonMatch) {
283
- const [, left, operator, right] = comparisonMatch;
284
- const operatorMap = {
285
- '===': '$eq', '!==': '$ne',
286
- '>=': '$gte', '<=': '$lte',
287
- '>': '$gt', '<': '$lt'
288
- };
289
-
290
- // 解析左侧(可能是字段或函数)
291
- const leftValue = /^(CONCAT|UPPER|LOWER|TRIM|SUBSTR|LENGTH|ABS|CEIL|FLOOR|ROUND|SQRT|POW|SIZE|IN|SLICE|FIRST|LAST|ARRAY_ELEM_AT|FILTER|MAP|INDEX_OF|CONCAT_ARRAYS|TYPE|NOT|EXISTS|IS_NUMBER|IS_ARRAY|SUM|AVG|MAX|MIN|COUNT|PUSH|ADD_TO_SET|YEAR|MONTH|DAY_OF_MONTH|HOUR|MINUTE|SECOND|SPLIT|REPLACE|INDEX_OF_STR|LTRIM|RTRIM|SUBSTR_CP|REGEX|MERGE_OBJECTS|TO_INT|TO_STRING|OBJECT_TO_ARRAY|ARRAY_TO_OBJECT|SET_UNION|SWITCH)\s*\(/i.test(left.trim())
292
- ? this._compileInnerExpression(left.trim(), targetDB)
293
- : `$${left.trim()}`;
294
-
295
- return {
296
- [operatorMap[operator]]: [leftValue, this._parseValue(right.trim())]
297
- };
298
- }
299
-
300
- throw new Error(`Unsupported expression: ${expression}`);
301
- }
302
-
303
- _parseValue(value) {
304
- // 检查是否是函数调用
305
- if (/^(CONCAT|UPPER|LOWER|TRIM|SUBSTR|LENGTH|ABS|CEIL|FLOOR|ROUND|SQRT|POW|SIZE|IN|SLICE|FIRST|LAST|ARRAY_ELEM_AT|FILTER|MAP|INDEX_OF|CONCAT_ARRAYS|TYPE|NOT|EXISTS|IS_NUMBER|IS_ARRAY|SUM|AVG|MAX|MIN|COUNT|PUSH|ADD_TO_SET|YEAR|MONTH|DAY_OF_MONTH|HOUR|MINUTE|SECOND|SPLIT|REPLACE|INDEX_OF_STR|LTRIM|RTRIM|SUBSTR_CP|REGEX|MERGE_OBJECTS|TO_INT|TO_STRING|OBJECT_TO_ARRAY|ARRAY_TO_OBJECT|SET_UNION|SWITCH)\s*\(/i.test(value)) {
306
- return this._compileInnerExpression(value, 'mongodb');
307
- }
308
-
309
- if (/^['"]/.test(value)) {
310
- return value.slice(1, -1); // 字符串
311
- } else if (value === 'null') {
312
- return null;
313
- } else if (value === 'true') {
314
- return true;
315
- } else if (value === 'false') {
316
- return false;
317
- } else if (!isNaN(value)) {
318
- return Number(value); // 数字
319
- } else {
320
- return `$${value}`; // 字段引用
321
- }
322
- }
323
-
324
- _parseOperand(operand, targetDB) {
325
- const trimmed = operand.trim();
326
-
327
- // 如果包含运算符,递归编译
328
- if (/[+\-*/%]/.test(trimmed)) {
329
- return this._compileInnerExpression(trimmed, targetDB);
330
- }
331
-
332
- return this._parseValue(trimmed);
333
- }
334
-
335
- _compileStringFunction(funcName, argsStr, targetDB) {
336
- // 解析函数参数
337
- const args = this._parseFunctionArgs(argsStr);
338
-
339
- switch (funcName) {
340
- case 'CONCAT': {
341
- const compiledArgs = args.map(arg => this._parseValue(arg));
342
- return { $concat: compiledArgs };
343
- }
344
-
345
- case 'UPPER': {
346
- return { $toUpper: this._parseValue(args[0]) };
347
- }
348
-
349
- case 'LOWER': {
350
- return { $toLower: this._parseValue(args[0]) };
351
- }
352
-
353
- case 'TRIM': {
354
- return { $trim: { input: this._parseValue(args[0]) } };
355
- }
356
-
357
- case 'SUBSTR': {
358
- return {
359
- $substr: [
360
- this._parseValue(args[0]),
361
- parseInt(args[1]),
362
- parseInt(args[2])
363
- ]
364
- };
365
- }
366
-
367
- case 'LENGTH': {
368
- return { $strLenCP: this._parseValue(args[0]) };
369
- }
370
-
371
- default:
372
- throw new Error(`Unsupported string function: ${funcName}`);
373
- }
374
- }
375
-
376
- _compileStringAdvancedFunction(funcName, argsStr, targetDB) {
377
- const args = this._parseFunctionArgs(argsStr);
378
-
379
- switch (funcName) {
380
- case 'SPLIT': {
381
- return {
382
- $split: [this._parseValue(args[0]), args[1].replace(/['"]/g, '')]
383
- };
384
- }
385
-
386
- case 'REPLACE': {
387
- return {
388
- $replaceAll: {
389
- input: this._parseValue(args[0]),
390
- find: args[1].replace(/['"]/g, ''),
391
- replacement: args[2].replace(/['"]/g, '')
392
- }
393
- };
394
- }
395
-
396
- case 'INDEX_OF_STR': {
397
- return {
398
- $indexOfBytes: [this._parseValue(args[0]), args[1].replace(/['"]/g, '')]
399
- };
400
- }
401
-
402
- case 'LTRIM': {
403
- return {
404
- $ltrim: { input: this._parseValue(args[0]) }
405
- };
406
- }
407
-
408
- case 'RTRIM': {
409
- return {
410
- $rtrim: { input: this._parseValue(args[0]) }
411
- };
412
- }
413
-
414
- case 'SUBSTR_CP': {
415
- return {
416
- $substrCP: [this._parseValue(args[0]), parseInt(args[1]), parseInt(args[2])]
417
- };
418
- }
419
-
420
- default:
421
- throw new Error(`Unsupported string advanced function: ${funcName}`);
422
- }
423
- }
424
-
425
- _compileMathFunction(funcName, argsStr, targetDB) {
426
- const args = this._parseFunctionArgs(argsStr);
427
-
428
- switch (funcName) {
429
- case 'ABS': {
430
- return { $abs: this._parseValue(args[0]) };
431
- }
432
-
433
- case 'CEIL': {
434
- return { $ceil: this._parseValue(args[0]) };
435
- }
436
-
437
- case 'FLOOR': {
438
- return { $floor: this._parseValue(args[0]) };
439
- }
440
-
441
- case 'ROUND': {
442
- return { $round: this._parseValue(args[0]) };
443
- }
444
-
445
- case 'SQRT': {
446
- return { $sqrt: this._parseValue(args[0]) };
447
- }
448
-
449
- case 'POW': {
450
- return {
451
- $pow: [
452
- this._parseValue(args[0]),
453
- this._parseValue(args[1])
454
- ]
455
- };
456
- }
457
-
458
- default:
459
- throw new Error(`Unsupported math function: ${funcName}`);
460
- }
461
- }
462
-
463
- _compileArrayFunction(funcName, argsStr, targetDB) {
464
- const args = this._parseFunctionArgs(argsStr);
465
-
466
- switch (funcName) {
467
- case 'SIZE': {
468
- return { $size: this._parseValue(args[0]) };
469
- }
470
-
471
- case 'IN': {
472
- return {
473
- $in: [this._parseValue(args[0]), this._parseValue(args[1])]
474
- };
475
- }
476
-
477
- case 'SLICE': {
478
- return {
479
- $slice: [this._parseValue(args[0]), parseInt(args[1])]
480
- };
481
- }
482
-
483
- case 'ARRAY_ELEM_AT': {
484
- // ARRAY_ELEM_AT(array, index) => { $arrayElemAt: ['$array', index] }
485
- return {
486
- $arrayElemAt: [this._parseValue(args[0]), parseInt(args[1])]
487
- };
488
- }
489
-
490
- case 'FIRST': {
491
- return { $first: this._parseValue(args[0]) };
492
- }
493
-
494
- case 'LAST': {
495
- return { $last: this._parseValue(args[0]) };
496
- }
497
-
498
- default:
499
- throw new Error(`Unsupported array function: ${funcName}`);
500
- }
501
- }
502
-
503
- _compileArrayAdvancedFunction(funcName, argsStr, targetDB) {
504
- const args = this._parseFunctionArgs(argsStr);
505
-
506
- switch (funcName) {
507
- case 'FILTER': {
508
- // FILTER(array, varName, condition)
509
- // Example: FILTER(tags, tag, tag.active === true)
510
- const arrayExpr = this._parseValue(args[0]);
511
- const varName = args[1].trim();
512
- const condition = args[2].trim();
513
-
514
- // 编译条件,替换变量引用
515
- const compiledCond = this._compileFilterCondition(condition, varName, targetDB);
516
-
517
- return {
518
- $filter: {
519
- input: arrayExpr,
520
- as: varName,
521
- cond: compiledCond
522
- }
523
- };
524
- }
525
-
526
- case 'MAP': {
527
- // MAP(array, varName, expression)
528
- // Example: MAP(tags, tag, tag.name)
529
- const arrayExpr = this._parseValue(args[0]);
530
- const varName = args[1].trim();
531
- const expr = args[2].trim();
532
-
533
- // 编译映射表达式
534
- const compiledExpr = this._compileMapExpression(expr, varName, targetDB);
535
-
536
- return {
537
- $map: {
538
- input: arrayExpr,
539
- as: varName,
540
- in: compiledExpr
541
- }
542
- };
543
- }
544
-
545
- case 'INDEX_OF': {
546
- // INDEX_OF(array, searchValue)
547
- return {
548
- $indexOfArray: [this._parseValue(args[0]), this._parseValue(args[1])]
549
- };
550
- }
551
-
552
- case 'CONCAT_ARRAYS': {
553
- // CONCAT_ARRAYS(array1, array2, ...)
554
- const arrays = args.map(arg => this._parseValue(arg));
555
- return { $concatArrays: arrays };
556
- }
557
-
558
- default:
559
- throw new Error(`Unsupported array advanced function: ${funcName}`);
560
- }
561
- }
562
-
563
- _compileFilterCondition(condition, varName, targetDB) {
564
- // 替换 varName.field 为 $$varName.field
565
- const replaced = condition.replace(new RegExp(`\\b${varName}\\.`, 'g'), `$$${varName}.`);
566
- // 编译表达式
567
- return this._compileInnerExpression(replaced, targetDB);
568
- }
569
-
570
- _compileMapExpression(expr, varName, targetDB) {
571
- // 检查是否是简单字段访问: tag.name
572
- if (expr.startsWith(`${varName}.`)) {
573
- const field = expr.substring(varName.length + 1);
574
- return `$$${varName}.${field}`;
575
- }
576
-
577
- // 检查是否是函数调用: UPPER(tag.name)
578
- if (/^[A-Z_]+\(/.test(expr)) {
579
- // 替换变量引用
580
- const replaced = expr.replace(new RegExp(`\\b${varName}\\.`, 'g'), `$$${varName}.`);
581
- return this._compileInnerExpression(replaced, targetDB);
582
- }
583
-
584
- // 默认处理
585
- return this._parseValue(expr);
586
- }
587
-
588
- _compileTypeFunction(funcName, argsStr, targetDB) {
589
- const args = this._parseFunctionArgs(argsStr);
590
-
591
- switch (funcName) {
592
- case 'TYPE': {
593
- return { $type: this._parseValue(args[0]) };
594
- }
595
-
596
- case 'NOT': {
597
- const expr = this._compileInnerExpression(args[0], targetDB);
598
- return { $not: [expr] };
599
- }
600
-
601
- case 'EXISTS': {
602
- return { $ne: [this._parseValue(args[0]), null] };
603
- }
604
-
605
- case 'IS_NUMBER': {
606
- return {
607
- $eq: [{ $type: this._parseValue(args[0]) }, 'number']
608
- };
609
- }
610
-
611
- case 'IS_ARRAY': {
612
- return { $isArray: this._parseValue(args[0]) };
613
- }
614
-
615
- default:
616
- throw new Error(`Unsupported type function: ${funcName}`);
617
- }
618
- }
619
-
620
- _compileAggregationFunction(funcName, argsStr, targetDB) {
621
- const args = argsStr ? this._parseFunctionArgs(argsStr) : [];
622
-
623
- switch (funcName) {
624
- case 'SUM': {
625
- // SUM(field) => { $sum: '$field' }
626
- // SUM(expr) => { $sum: expr }
627
- if (args.length === 0) {
628
- return { $sum: 1 };
629
- }
630
- return { $sum: this._parseValue(args[0]) };
631
- }
632
-
633
- case 'AVG': {
634
- // AVG(field) => { $avg: '$field' }
635
- return { $avg: this._parseValue(args[0]) };
636
- }
637
-
638
- case 'MAX': {
639
- // MAX(field) => { $max: '$field' }
640
- return { $max: this._parseValue(args[0]) };
641
- }
642
-
643
- case 'MIN': {
644
- // MIN(field) => { $min: '$field' }
645
- return { $min: this._parseValue(args[0]) };
646
- }
647
-
648
- case 'COUNT': {
649
- // COUNT() => { $sum: 1 }
650
- return { $sum: 1 };
651
- }
652
-
653
- case 'PUSH': {
654
- // PUSH(field) => { $push: '$field' }
655
- return { $push: this._parseValue(args[0]) };
656
- }
657
-
658
- case 'ADD_TO_SET': {
659
- // ADD_TO_SET(field) => { $addToSet: '$field' }
660
- return { $addToSet: this._parseValue(args[0]) };
661
- }
662
-
663
- default:
664
- throw new Error(`Unsupported aggregation function: ${funcName}`);
665
- }
666
- }
667
-
668
- _compileDateFunction(funcName, argsStr, targetDB) {
669
- const args = this._parseFunctionArgs(argsStr);
670
-
671
- switch (funcName) {
672
- case 'YEAR': {
673
- return { $year: this._parseValue(args[0]) };
674
- }
675
-
676
- case 'MONTH': {
677
- return { $month: this._parseValue(args[0]) };
678
- }
679
-
680
- case 'DAY_OF_MONTH': {
681
- return { $dayOfMonth: this._parseValue(args[0]) };
682
- }
683
-
684
- case 'HOUR': {
685
- return { $hour: this._parseValue(args[0]) };
686
- }
687
-
688
- case 'MINUTE': {
689
- return { $minute: this._parseValue(args[0]) };
690
- }
691
-
692
- case 'SECOND': {
693
- return { $second: this._parseValue(args[0]) };
694
- }
695
-
696
- default:
697
- throw new Error(`Unsupported date function: ${funcName}`);
698
- }
699
- }
700
-
701
- /**
702
- * 编译日期高级函数(P0 新增)
703
- * 支持:DATE_ADD, DATE_SUBTRACT, DATE_DIFF, DATE_TO_STRING, DATE_FROM_STRING
704
- */
705
- _compileDateAdvancedFunction(funcName, argsStr, targetDB) {
706
- const args = this._parseFunctionArgs(argsStr);
707
-
708
- switch (funcName) {
709
- case 'DATE_ADD': {
710
- // DATE_ADD(date, amount, unit) => { $dateAdd: { startDate: '$date', unit: 'day', amount: 7 } }
711
- if (args.length !== 3) {
712
- throw new Error('DATE_ADD requires 3 arguments: DATE_ADD(date, amount, unit)');
713
- }
714
-
715
- const dateValue = this._parseValue(args[0]);
716
- const amount = this._parseValue(args[1]);
717
- const unit = args[2].replace(/['"]/g, ''); // 移除引号
718
-
719
- // 验证时间单位
720
- const validUnits = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
721
- if (!validUnits.includes(unit)) {
722
- throw new Error(`Invalid time unit for DATE_ADD: ${unit}. Valid units: ${validUnits.join(', ')}`);
723
- }
724
-
725
- return {
726
- $dateAdd: {
727
- startDate: dateValue,
728
- unit: unit,
729
- amount: amount
730
- }
731
- };
732
- }
733
-
734
- case 'DATE_SUBTRACT': {
735
- // DATE_SUBTRACT(date, amount, unit) => { $dateSubtract: { startDate: '$date', unit: 'day', amount: 7 } }
736
- if (args.length !== 3) {
737
- throw new Error('DATE_SUBTRACT requires 3 arguments: DATE_SUBTRACT(date, amount, unit)');
738
- }
739
-
740
- const dateValue = this._parseValue(args[0]);
741
- const amount = this._parseValue(args[1]);
742
- const unit = args[2].replace(/['"]/g, '');
743
-
744
- const validUnits = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
745
- if (!validUnits.includes(unit)) {
746
- throw new Error(`Invalid time unit for DATE_SUBTRACT: ${unit}. Valid units: ${validUnits.join(', ')}`);
747
- }
748
-
749
- return {
750
- $dateSubtract: {
751
- startDate: dateValue,
752
- unit: unit,
753
- amount: amount
754
- }
755
- };
756
- }
757
-
758
- case 'DATE_DIFF': {
759
- // DATE_DIFF(endDate, startDate, unit) => { $dateDiff: { startDate: '$start', endDate: '$end', unit: 'day' } }
760
- if (args.length !== 3) {
761
- throw new Error('DATE_DIFF requires 3 arguments: DATE_DIFF(endDate, startDate, unit)');
762
- }
763
-
764
- const endDate = this._parseValue(args[0]);
765
- const startDate = this._parseValue(args[1]);
766
- const unit = args[2].replace(/['"]/g, '');
767
-
768
- const validUnits = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
769
- if (!validUnits.includes(unit)) {
770
- throw new Error(`Invalid time unit for DATE_DIFF: ${unit}. Valid units: ${validUnits.join(', ')}`);
771
- }
772
-
773
- return {
774
- $dateDiff: {
775
- startDate: startDate,
776
- endDate: endDate,
777
- unit: unit
778
- }
779
- };
780
- }
781
-
782
- case 'DATE_TO_STRING': {
783
- // DATE_TO_STRING(date, format) => { $dateToString: { date: '$date', format: '%Y-%m-%d' } }
784
- if (args.length !== 2) {
785
- throw new Error('DATE_TO_STRING requires 2 arguments: DATE_TO_STRING(date, format)');
786
- }
787
-
788
- const dateValue = this._parseValue(args[0]);
789
- const format = args[1].replace(/['"]/g, ''); // 移除引号
790
-
791
- return {
792
- $dateToString: {
793
- date: dateValue,
794
- format: format
795
- }
796
- };
797
- }
798
-
799
- case 'DATE_FROM_STRING': {
800
- // DATE_FROM_STRING(dateString, format) => { $dateFromString: { dateString: '$str', format: '%Y-%m-%d' } }
801
- if (args.length < 1 || args.length > 2) {
802
- throw new Error('DATE_FROM_STRING requires 1-2 arguments: DATE_FROM_STRING(dateString [, format])');
803
- }
804
-
805
- const dateString = this._parseValue(args[0]);
806
- const result = {
807
- $dateFromString: {
808
- dateString: dateString
809
- }
810
- };
811
-
812
- // format 参数可选
813
- if (args.length === 2) {
814
- const format = args[1].replace(/['"]/g, '');
815
- result.$dateFromString.format = format;
816
- }
817
-
818
- return result;
819
- }
820
-
821
- default:
822
- throw new Error(`Unsupported date advanced function: ${funcName}`);
823
- }
824
- }
825
-
826
- _compileHighFrequencyFunction(funcName, argsStr, targetDB) {
827
- const args = this._parseFunctionArgs(argsStr);
828
-
829
- switch (funcName) {
830
- case 'REGEX': {
831
- // REGEX(field, pattern) => { $regexMatch: { input: '$field', regex: 'pattern' } }
832
- return {
833
- $regexMatch: {
834
- input: this._parseValue(args[0]),
835
- regex: args[1].replace(/['"]/g, '')
836
- }
837
- };
838
- }
839
-
840
- case 'MERGE_OBJECTS': {
841
- // MERGE_OBJECTS(obj1, obj2) => { $mergeObjects: ['$obj1', {...}] }
842
- // 处理对象字面量
843
- const parsedArgs = args.map(arg => {
844
- if (arg.trim().startsWith('{')) {
845
- // 对象字面量,需要解析
846
- try {
847
- return JSON.parse(arg.trim());
848
- } catch {
849
- return this._parseValue(arg);
850
- }
851
- }
852
- return this._parseValue(arg);
853
- });
854
- return { $mergeObjects: parsedArgs };
855
- }
856
-
857
- case 'TO_INT': {
858
- // TO_INT(value) => { $toInt: '$value' }
859
- return { $toInt: this._parseValue(args[0]) };
860
- }
861
-
862
- case 'TO_STRING': {
863
- // TO_STRING(value) => { $toString: '$value' }
864
- return { $toString: this._parseValue(args[0]) };
865
- }
866
-
867
- case 'OBJECT_TO_ARRAY': {
868
- // OBJECT_TO_ARRAY(obj) => { $objectToArray: '$obj' }
869
- return { $objectToArray: this._parseValue(args[0]) };
870
- }
871
-
872
- case 'ARRAY_TO_OBJECT': {
873
- // ARRAY_TO_OBJECT(array) => { $arrayToObject: '$array' }
874
- return { $arrayToObject: this._parseValue(args[0]) };
875
- }
876
-
877
- case 'SET_UNION': {
878
- // SET_UNION(array1, array2) => { $setUnion: ['$array1', '$array2'] }
879
- const parsedArgs = args.map(arg => {
880
- if (arg.trim().startsWith('[')) {
881
- // 数组字面量
882
- try {
883
- return JSON.parse(arg.trim());
884
- } catch {
885
- return this._parseValue(arg);
886
- }
887
- }
888
- return this._parseValue(arg);
889
- });
890
- return { $setUnion: parsedArgs };
891
- }
892
-
893
- default:
894
- throw new Error(`Unsupported high frequency function: ${funcName}`);
895
- }
896
- }
897
-
898
- _compileSwitchFunction(argsStr, targetDB) {
899
- const args = this._parseFunctionArgs(argsStr);
900
-
901
- // SWITCH(cond1, val1, cond2, val2, ..., default)
902
- // => { $switch: { branches: [{case, then}, ...], default } }
903
-
904
- if (args.length < 2) {
905
- throw new Error('SWITCH requires at least 2 arguments');
906
- }
907
-
908
- const branches = [];
909
- let defaultValue = null;
910
-
911
- // 解析分支:每两个参数一组 (condition, value)
912
- for (let i = 0; i < args.length - 1; i += 2) {
913
- if (i + 1 < args.length) {
914
- const condition = this._compileInnerExpression(args[i], targetDB);
915
- const value = this._parseValue(args[i + 1]);
916
- branches.push({ case: condition, then: value });
917
- }
918
- }
919
-
920
- // 如果参数是奇数,最后一个是default值
921
- if (args.length % 2 === 1) {
922
- defaultValue = this._parseValue(args[args.length - 1]);
923
- }
924
-
925
- const result = {
926
- $switch: {
927
- branches: branches
928
- }
929
- };
930
-
931
- if (defaultValue !== null) {
932
- result.$switch.default = defaultValue;
933
- }
934
-
935
- return result;
936
- }
937
-
938
- _parseFunctionArgs(argsStr) {
939
- // 简单的逗号分隔(处理字符串和嵌套括号)
940
- const args = [];
941
- let current = '';
942
- let inString = false;
943
- let stringChar = null;
944
- let parenDepth = 0;
945
-
946
- for (let i = 0; i < argsStr.length; i++) {
947
- const char = argsStr[i];
948
-
949
- if ((char === '"' || char === "'") && (i === 0 || argsStr[i-1] !== '\\')) {
950
- if (!inString) {
951
- inString = true;
952
- stringChar = char;
953
- } else if (char === stringChar) {
954
- inString = false;
955
- stringChar = null;
956
- }
957
- current += char;
958
- } else if (char === '(' && !inString) {
959
- parenDepth++;
960
- current += char;
961
- } else if (char === ')' && !inString) {
962
- parenDepth--;
963
- current += char;
964
- } else if (char === ',' && !inString && parenDepth === 0) {
965
- args.push(current.trim());
966
- current = '';
967
- } else {
968
- current += char;
969
- }
970
- }
971
-
972
- if (current.trim()) {
973
- args.push(current.trim());
974
- }
975
-
976
- return args;
977
- }
978
-
979
- /**
980
- * 递归编译管道中的所有表达式
981
- * @param {Array} pipeline - 聚合管道
982
- * @param {Object} options - 编译选项
983
- * @returns {Array} 编译后的管道
984
- */
985
- compilePipeline(pipeline, options = {}) {
986
- if (!Array.isArray(pipeline)) {
987
- throw new TypeError('Pipeline must be an array');
988
- }
989
-
990
- return pipeline.map(stage => this._compileStage(stage, options));
991
- }
992
-
993
- /**
994
- * 编译单个管道阶段
995
- * @param {Object} stage - 管道阶段
996
- * @param {Object} options - 编译选项
997
- * @returns {Object} 编译后的阶段
998
- * @private
999
- */
1000
- _compileStage(stage, options) {
1001
- if (!stage || typeof stage !== 'object') {
1002
- return stage;
1003
- }
1004
-
1005
- if (Array.isArray(stage)) {
1006
- return stage.map(item => this._compileStage(item, options));
1007
- }
1008
-
1009
- if (isExpressionObject(stage)) {
1010
- const context = options.context || 'match';
1011
- return this.compile(stage, { ...options, context });
1012
- }
1013
-
1014
- // 检测阶段类型
1015
- const stageKeys = Object.keys(stage);
1016
- if (stageKeys.length > 0) {
1017
- const stageKey = stageKeys[0];
1018
-
1019
- // 根据阶段类型设置上下文
1020
- let context = 'match';
1021
- if (stageKey === '$project' || stageKey === '$addFields' || stageKey === '$set') {
1022
- context = 'project';
1023
- } else if (stageKey === '$group') {
1024
- context = 'group';
1025
- }
1026
-
1027
- // 递归编译阶段内容
1028
- const compiled = {};
1029
- for (const key in stage) {
1030
- if (stage.hasOwnProperty(key)) {
1031
- compiled[key] = this._compileStageValue(stage[key], { ...options, context });
1032
- }
1033
- }
1034
-
1035
- return compiled;
1036
- }
1037
-
1038
- // 默认递归处理
1039
- const compiled = {};
1040
- for (const key in stage) {
1041
- if (stage.hasOwnProperty(key)) {
1042
- compiled[key] = this._compileStage(stage[key], options);
1043
- }
1044
- }
1045
-
1046
- return compiled;
1047
- }
1048
-
1049
- _compileStageValue(value, options) {
1050
- if (!value || typeof value !== 'object') {
1051
- return value;
1052
- }
1053
-
1054
- if (Array.isArray(value)) {
1055
- return value.map(item => this._compileStageValue(item, options));
1056
- }
1057
-
1058
- if (isExpressionObject(value)) {
1059
- return this.compile(value, options);
1060
- }
1061
-
1062
- const compiled = {};
1063
- for (const key in value) {
1064
- if (value.hasOwnProperty(key)) {
1065
- compiled[key] = this._compileStageValue(value[key], options);
1066
- }
1067
- }
1068
-
1069
- return compiled;
1070
- }
1071
-
1072
- /**
1073
- * 获取缓存统计
1074
- * @returns {Object} 缓存统计
1075
- */
1076
- getStats() {
1077
- return this.cache.getStats();
1078
- }
1079
-
1080
- /**
1081
- * 清空缓存
1082
- */
1083
- clearCache() {
1084
- this.cache.clear();
1085
- }
1086
- }
1087
-
1088
- module.exports = ExpressionCompiler;
1089
-
1090
-