@aetherframework/database 1.1.1 → 1.1.2

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 (47) hide show
  1. package/examples/mysql-test-pressure.js +1530 -0
  2. package/examples/test-direct.js +116 -0
  3. package/examples/transaction_example.js +127 -0
  4. package/package.json +3 -1
  5. package/src/DatabaseManager.js +565 -0
  6. package/src/core/ConnectionManager.js +351 -0
  7. package/src/core/DatabaseFactory.js +188 -0
  8. package/src/core/MongoQueryBuilder.js +576 -0
  9. package/src/core/PluginManager.js +968 -0
  10. package/src/core/QueryBuilder.js +4394 -0
  11. package/src/core/TransactionManager.js +40 -0
  12. package/src/drivers/clickhouse-driver.js +272 -0
  13. package/src/drivers/index.js +273 -0
  14. package/src/drivers/mongodb-driver.js +87 -0
  15. package/src/drivers/mssql-driver.js +117 -0
  16. package/src/drivers/mysql-driver.js +169 -0
  17. package/src/drivers/oracle-driver.js +101 -0
  18. package/src/drivers/postgres-driver.js +234 -0
  19. package/src/drivers/redis-driver.js +52 -0
  20. package/src/drivers/sqlite-driver.js +67 -0
  21. package/src/middleware/connection-pool.js +455 -0
  22. package/src/middleware/performance-monitor.js +652 -0
  23. package/src/middleware/query-cache.js +500 -0
  24. package/src/middleware/query-logger.js +262 -0
  25. package/src/plugins/AuditPlugin.js +447 -0
  26. package/src/plugins/BasePlugin.js +418 -0
  27. package/src/plugins/BatchOperationPlugin.js +165 -0
  28. package/src/plugins/CachePlugin.js +407 -0
  29. package/src/plugins/CtePlugin.js +523 -0
  30. package/src/plugins/DistributedPlugin.js +543 -0
  31. package/src/plugins/EncryptionPlugin.js +211 -0
  32. package/src/plugins/FullTextSearchPlugin.js +164 -0
  33. package/src/plugins/GeospatialPlugin.js +219 -0
  34. package/src/plugins/GraphQLPlugin.js +162 -0
  35. package/src/plugins/HookPlugin.js +211 -0
  36. package/src/plugins/JsonPlugin.js +366 -0
  37. package/src/plugins/OptimisticLockPlugin.js +374 -0
  38. package/src/plugins/PerformancePlugin.js +175 -0
  39. package/src/plugins/ResiliencePlugin.js +114 -0
  40. package/src/plugins/ShardingPlugin.js +227 -0
  41. package/src/plugins/SoftDeletePlugin.js +258 -0
  42. package/src/plugins/SyncPlugin.js +373 -0
  43. package/src/plugins/VersioningPlugin.js +314 -0
  44. package/src/plugins/WindowFunctionPlugin.js +343 -0
  45. package/src/utils/config-loader.js +632 -0
  46. package/src/utils/error-handler.js +724 -0
  47. package/src/utils/migration-runner.js +1066 -0
@@ -0,0 +1,576 @@
1
+ /**
2
+ * @license MIT
3
+ * Copyright (c) 2026-present AetherFramework Contributors.
4
+ * SPDX-License-Identifier: MIT
5
+ * @module @aetherframework/database/core/MongoQueryBuilder
6
+ */
7
+
8
+ import EventEmitter from 'events';
9
+
10
+ /**
11
+ * MongoDB 查询构建器
12
+ * 专为 MongoDB 文档数据库设计的链式查询构建器
13
+ */
14
+ class MongoQueryBuilder extends EventEmitter {
15
+ /**
16
+ * 构造函数
17
+ * @param {string} collectionName - 集合名称
18
+ * @param {MongoDBDriver} driver - MongoDB 驱动实例
19
+ * @param {object} connection - MongoDB 连接
20
+ */
21
+ constructor(collectionName, driver, connection) {
22
+ super();
23
+ this.collectionName = collectionName;
24
+ this.driver = driver;
25
+ this.connection = connection;
26
+
27
+ // 查询状态
28
+ this.query = {
29
+ type: 'find', // find, aggregate, count, distinct, etc.
30
+ filter: {},
31
+ projection: {},
32
+ sort: {},
33
+ skip: 0,
34
+ limit: 0,
35
+ options: {},
36
+ pipeline: [],
37
+ update: {},
38
+ aggregation: []
39
+ };
40
+
41
+ // 操作统计
42
+ this.stats = {
43
+ executionTime: 0,
44
+ documentsExamined: 0,
45
+ documentsReturned: 0
46
+ };
47
+ }
48
+
49
+ /**
50
+ * 设置查询过滤器
51
+ * @param {object|string} field - 字段名或查询对象
52
+ * @param {*} operator - 操作符或值
53
+ * @param {*} value - 值(当 operator 为操作符时)
54
+ * @returns {MongoQueryBuilder}
55
+ */
56
+ where(field, operator, value) {
57
+ if (typeof field === 'object') {
58
+ // 直接传入查询对象
59
+ Object.assign(this.query.filter, field);
60
+ } else if (value === undefined) {
61
+ // where('field', value) 简写,默认为相等
62
+ this.query.filter[field] = operator;
63
+ } else {
64
+ // where('field', 'operator', value)
65
+ if (!this.query.filter[field]) {
66
+ this.query.filter[field] = {};
67
+ }
68
+ this.query.filter[field][`$${operator}`] = value;
69
+ }
70
+ return this;
71
+ }
72
+
73
+ /**
74
+ * 等于条件
75
+ * @param {string} field - 字段名
76
+ * @param {*} value - 值
77
+ * @returns {MongoQueryBuilder}
78
+ */
79
+ eq(field, value) {
80
+ return this.where(field, value);
81
+ }
82
+
83
+ /**
84
+ * 不等于条件
85
+ * @param {string} field - 字段名
86
+ * @param {*} value - 值
87
+ * @returns {MongoQueryBuilder}
88
+ */
89
+ ne(field, value) {
90
+ return this.where(field, 'ne', value);
91
+ }
92
+
93
+ /**
94
+ * 大于条件
95
+ * @param {string} field - 字段名
96
+ * @param {*} value - 值
97
+ * @returns {MongoQueryBuilder}
98
+ */
99
+ gt(field, value) {
100
+ return this.where(field, 'gt', value);
101
+ }
102
+
103
+ /**
104
+ * 大于等于条件
105
+ * @param {string} field - 字段名
106
+ * @param {*} value - 值
107
+ * @returns {MongoQueryBuilder}
108
+ */
109
+ gte(field, value) {
110
+ return this.where(field, 'gte', value);
111
+ }
112
+
113
+ /**
114
+ * 小于条件
115
+ * @param {string} field - 字段名
116
+ * @param {*} value - 值
117
+ * @returns {MongoQueryBuilder}
118
+ */
119
+ lt(field, value) {
120
+ return this.where(field, 'lt', value);
121
+ }
122
+
123
+ /**
124
+ * 小于等于条件
125
+ * @param {string} field - 字段名
126
+ * @param {*} value - 值
127
+ * @returns {MongoQueryBuilder}
128
+ */
129
+ lte(field, value) {
130
+ return this.where(field, 'lte', value);
131
+ }
132
+
133
+ /**
134
+ * IN 条件
135
+ * @param {string} field - 字段名
136
+ * @param {Array} values - 值数组
137
+ * @returns {MongoQueryBuilder}
138
+ */
139
+ in(field, values) {
140
+ return this.where(field, 'in', values);
141
+ }
142
+
143
+ /**
144
+ * NOT IN 条件
145
+ * @param {string} field - 字段名
146
+ * @param {Array} values - 值数组
147
+ * @returns {MongoQueryBuilder}
148
+ */
149
+ nin(field, values) {
150
+ return this.where(field, 'nin', values);
151
+ }
152
+
153
+ /**
154
+ * 正则表达式匹配
155
+ * @param {string} field - 字段名
156
+ * @param {string|RegExp} pattern - 正则表达式
157
+ * @param {string} options - 选项(如 'i' 忽略大小写)
158
+ * @returns {MongoQueryBuilder}
159
+ */
160
+ regex(field, pattern, options = '') {
161
+ this.query.filter[field] = { $regex: pattern, $options: options };
162
+ return this;
163
+ }
164
+
165
+ /**
166
+ * 文本搜索
167
+ * @param {string} search - 搜索文本
168
+ * @param {string} language - 语言(可选)
169
+ * @returns {MongoQueryBuilder}
170
+ */
171
+ text(search, language = null) {
172
+ this.query.filter.$text = { $search: search };
173
+ if (language) {
174
+ this.query.filter.$text.$language = language;
175
+ }
176
+ return this;
177
+ }
178
+
179
+ /**
180
+ * 选择返回字段
181
+ * @param {...string} fields - 字段名
182
+ * @returns {MongoQueryBuilder}
183
+ */
184
+ select(...fields) {
185
+ fields.forEach(field => {
186
+ if (field.startsWith('-')) {
187
+ // 排除字段
188
+ this.query.projection[field.substring(1)] = 0;
189
+ } else {
190
+ // 包含字段
191
+ this.query.projection[field] = 1;
192
+ }
193
+ });
194
+ return this;
195
+ }
196
+
197
+ /**
198
+ * 排序
199
+ * @param {string|object} field - 字段名或排序对象
200
+ * @param {number} direction - 方向:1 升序,-1 降序
201
+ * @returns {MongoQueryBuilder}
202
+ */
203
+ orderBy(field, direction = 1) {
204
+ if (typeof field === 'object') {
205
+ Object.assign(this.query.sort, field);
206
+ } else {
207
+ this.query.sort[field] = direction;
208
+ }
209
+ return this;
210
+ }
211
+
212
+ /**
213
+ * 跳过文档数
214
+ * @param {number} skip - 跳过的文档数
215
+ * @returns {MongoQueryBuilder}
216
+ */
217
+ skip(skip) {
218
+ this.query.skip = skip;
219
+ return this;
220
+ }
221
+
222
+ /**
223
+ * 限制返回文档数
224
+ * @param {number} limit - 限制数量
225
+ * @returns {MongoQueryBuilder}
226
+ */
227
+ limit(limit) {
228
+ this.query.limit = limit;
229
+ return this;
230
+ }
231
+
232
+ /**
233
+ * 设置查询选项
234
+ * @param {object} options - MongoDB 查询选项
235
+ * @returns {MongoQueryBuilder}
236
+ */
237
+ options(options) {
238
+ Object.assign(this.query.options, options);
239
+ return this;
240
+ }
241
+
242
+ /**
243
+ * 聚合管道阶段
244
+ * @param {object} stage - 聚合阶段
245
+ * @returns {MongoQueryBuilder}
246
+ */
247
+ pipeline(stage) {
248
+ this.query.pipeline.push(stage);
249
+ return this;
250
+ }
251
+
252
+ /**
253
+ * 匹配阶段
254
+ * @param {object} filter - 过滤条件
255
+ * @returns {MongoQueryBuilder}
256
+ */
257
+ match(filter) {
258
+ return this.pipeline({ $match: filter });
259
+ }
260
+
261
+ /**
262
+ * 分组阶段
263
+ * @param {object} group - 分组条件
264
+ * @returns {MongoQueryBuilder}
265
+ */
266
+ group(group) {
267
+ return this.pipeline({ $group: group });
268
+ }
269
+
270
+ /**
271
+ * 排序阶段
272
+ * @param {object} sort - 排序条件
273
+ * @returns {MongoQueryBuilder}
274
+ */
275
+ sortAgg(sort) {
276
+ return this.pipeline({ $sort: sort });
277
+ }
278
+
279
+ /**
280
+ * 限制阶段
281
+ * @param {number} limit - 限制数量
282
+ * @returns {MongoQueryBuilder}
283
+ */
284
+ limitAgg(limit) {
285
+ return this.pipeline({ $limit: limit });
286
+ }
287
+
288
+ /**
289
+ * 跳过阶段
290
+ * @param {number} skip - 跳过数量
291
+ * @returns {MongoQueryBuilder}
292
+ */
293
+ skipAgg(skip) {
294
+ return this.pipeline({ $skip: skip });
295
+ }
296
+
297
+ /**
298
+ * 项目阶段
299
+ * @param {object} project - 投影条件
300
+ * @returns {MongoQueryBuilder}
301
+ */
302
+ project(project) {
303
+ return this.pipeline({ $project: project });
304
+ }
305
+
306
+ /**
307
+ * 查找文档
308
+ * @returns {Promise<Array>}
309
+ */
310
+ async find() {
311
+ this.query.type = 'find';
312
+ const startTime = Date.now();
313
+
314
+ try {
315
+ const result = await this.driver.query(
316
+ this.connection,
317
+ this.collectionName,
318
+ this.query.filter,
319
+ {
320
+ projection: this.query.projection,
321
+ sort: this.query.sort,
322
+ skip: this.query.skip,
323
+ limit: this.query.limit,
324
+ ...this.query.options
325
+ }
326
+ );
327
+
328
+ this.stats.executionTime = Date.now() - startTime;
329
+ this.stats.documentsReturned = result.rows.length;
330
+
331
+ return result.rows;
332
+ } catch (error) {
333
+ this.emit('error', error);
334
+ throw error;
335
+ }
336
+ }
337
+
338
+ /**
339
+ * 查找单个文档
340
+ * @returns {Promise<object|null>}
341
+ */
342
+ async findOne() {
343
+ this.query.type = 'findOne';
344
+ this.query.limit = 1;
345
+
346
+ const results = await this.find();
347
+ return results || null;
348
+ }
349
+
350
+ /**
351
+ * 执行聚合查询
352
+ * @returns {Promise<Array>}
353
+ */
354
+ async aggregate() {
355
+ this.query.type = 'aggregate';
356
+ const startTime = Date.now();
357
+
358
+ try {
359
+ const collection = this.connection.collection(this.collectionName);
360
+ const cursor = collection.aggregate(this.query.pipeline);
361
+ const rows = await cursor.toArray();
362
+
363
+ this.stats.executionTime = Date.now() - startTime;
364
+ this.stats.documentsReturned = rows.length;
365
+
366
+ return rows;
367
+ } catch (error) {
368
+ this.emit('error', error);
369
+ throw error;
370
+ }
371
+ }
372
+
373
+ /**
374
+ * 计数
375
+ * @returns {Promise<number>}
376
+ */
377
+ async count() {
378
+ this.query.type = 'count';
379
+ const startTime = Date.now();
380
+
381
+ try {
382
+ const collection = this.connection.collection(this.collectionName);
383
+ const count = await collection.countDocuments(this.query.filter, this.query.options);
384
+
385
+ this.stats.executionTime = Date.now() - startTime;
386
+ return count;
387
+ } catch (error) {
388
+ this.emit('error', error);
389
+ throw error;
390
+ }
391
+ }
392
+
393
+ /**
394
+ * 去重
395
+ * @param {string} field - 字段名
396
+ * @returns {Promise<Array>}
397
+ */
398
+ async distinct(field) {
399
+ this.query.type = 'distinct';
400
+ const startTime = Date.now();
401
+
402
+ try {
403
+ const collection = this.connection.collection(this.collectionName);
404
+ const values = await collection.distinct(field, this.query.filter, this.query.options);
405
+
406
+ this.stats.executionTime = Date.now() - startTime;
407
+ return values;
408
+ } catch (error) {
409
+ this.emit('error', error);
410
+ throw error;
411
+ }
412
+ }
413
+
414
+ /**
415
+ * 插入文档
416
+ * @param {object|Array} data - 要插入的数据
417
+ * @returns {Promise<object>}
418
+ */
419
+ async insert(data) {
420
+ this.query.type = 'insert';
421
+ const startTime = Date.now();
422
+
423
+ try {
424
+ const result = await this.driver.execute(
425
+ this.connection,
426
+ this.collectionName,
427
+ 'insert',
428
+ data,
429
+ this.query.options
430
+ );
431
+
432
+ this.stats.executionTime = Date.now() - startTime;
433
+ return result;
434
+ } catch (error) {
435
+ this.emit('error', error);
436
+ throw error;
437
+ }
438
+ }
439
+
440
+ /**
441
+ * 更新文档
442
+ * @param {object} filter - 过滤条件
443
+ * @param {object} update - 更新操作
444
+ * @param {object} options - 更新选项
445
+ * @returns {Promise<object>}
446
+ */
447
+ async update(filter, update, options = {}) {
448
+ this.query.type = 'update';
449
+ const startTime = Date.now();
450
+
451
+ try {
452
+ const result = await this.driver.execute(
453
+ this.connection,
454
+ this.collectionName,
455
+ 'update',
456
+ { filter, update },
457
+ { ...this.query.options, ...options }
458
+ );
459
+
460
+ this.stats.executionTime = Date.now() - startTime;
461
+ return result;
462
+ } catch (error) {
463
+ this.emit('error', error);
464
+ throw error;
465
+ }
466
+ }
467
+
468
+ /**
469
+ * 删除文档
470
+ * @param {object} filter - 过滤条件
471
+ * @param {object} options - 删除选项
472
+ * @returns {Promise<object>}
473
+ */
474
+ async delete(filter, options = {}) {
475
+ this.query.type = 'delete';
476
+ const startTime = Date.now();
477
+
478
+ try {
479
+ const result = await this.driver.execute(
480
+ this.connection,
481
+ this.collectionName,
482
+ 'delete',
483
+ { filter },
484
+ { ...this.query.options, ...options }
485
+ );
486
+
487
+ this.stats.executionTime = Date.now() - startTime;
488
+ return result;
489
+ } catch (error) {
490
+ this.emit('error', error);
491
+ throw error;
492
+ }
493
+ }
494
+
495
+ /**
496
+ * 批量插入
497
+ * @param {Array} documents - 文档数组
498
+ * @returns {Promise<object>}
499
+ */
500
+ async insertMany(documents) {
501
+ const collection = this.connection.collection(this.collectionName);
502
+ const result = await collection.insertMany(documents, this.query.options);
503
+ return result;
504
+ }
505
+
506
+ /**
507
+ * 批量更新
508
+ * @param {object} filter - 过滤条件
509
+ * @param {object} update - 更新操作
510
+ * @param {object} options - 更新选项
511
+ * @returns {Promise<object>}
512
+ */
513
+ async updateMany(filter, update, options = {}) {
514
+ const collection = this.connection.collection(this.collectionName);
515
+ const result = await collection.updateMany(filter, update, { ...this.query.options, ...options });
516
+ return result;
517
+ }
518
+
519
+ /**
520
+ * 批量删除
521
+ * @param {object} filter - 过滤条件
522
+ * @param {object} options - 删除选项
523
+ * @returns {Promise<object>}
524
+ */
525
+ async deleteMany(filter, options = {}) {
526
+ const collection = this.connection.collection(this.collectionName);
527
+ const result = await collection.deleteMany(filter, { ...this.query.options, ...options });
528
+ return result;
529
+ }
530
+
531
+ /**
532
+ * 获取查询统计信息
533
+ * @returns {object}
534
+ */
535
+ getStats() {
536
+ return { ...this.stats };
537
+ }
538
+
539
+ /**
540
+ * 重置查询状态
541
+ * @returns {MongoQueryBuilder}
542
+ */
543
+ reset() {
544
+ this.query = {
545
+ type: 'find',
546
+ filter: {},
547
+ projection: {},
548
+ sort: {},
549
+ skip: 0,
550
+ limit: 0,
551
+ options: {},
552
+ pipeline: [],
553
+ update: {},
554
+ aggregation: []
555
+ };
556
+ this.stats = {
557
+ executionTime: 0,
558
+ documentsExamined: 0,
559
+ documentsReturned: 0
560
+ };
561
+ return this;
562
+ }
563
+
564
+ /**
565
+ * 获取构建的查询对象(用于调试)
566
+ * @returns {object}
567
+ */
568
+ toQuery() {
569
+ return {
570
+ collection: this.collectionName,
571
+ ...this.query
572
+ };
573
+ }
574
+ }
575
+
576
+ export default MongoQueryBuilder;