mm_mongodb 1.5.1 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +353 -612
- package/index.js +673 -430
- package/package.json +3 -3
- package/test.js +4 -5
package/index.js
CHANGED
|
@@ -4,21 +4,22 @@
|
|
|
4
4
|
* @version 1.2.1
|
|
5
5
|
*/
|
|
6
6
|
const {
|
|
7
|
-
|
|
8
|
-
} = require('
|
|
7
|
+
Base
|
|
8
|
+
} = require('mm_expand');
|
|
9
9
|
const MongoClient = require('mongodb').MongoClient;
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @description MongoDB帮助类
|
|
13
13
|
*/
|
|
14
|
-
class MongoDB extends
|
|
14
|
+
class MongoDB extends Base {
|
|
15
15
|
/**
|
|
16
16
|
* @description 创建MongoDB帮助类函数 (构造函数)
|
|
17
17
|
* @param {Object} config 配置参数
|
|
18
18
|
* @constructor
|
|
19
19
|
*/
|
|
20
20
|
constructor(config) {
|
|
21
|
-
super(
|
|
21
|
+
super();
|
|
22
|
+
this.config = {
|
|
22
23
|
// 服务器地址
|
|
23
24
|
host: "localhost",
|
|
24
25
|
// 端口号
|
|
@@ -26,26 +27,17 @@ class MongoDB extends BaseService {
|
|
|
26
27
|
// 数据库名
|
|
27
28
|
database: "mm",
|
|
28
29
|
// 用户名
|
|
29
|
-
user: "
|
|
30
|
+
user: "",
|
|
30
31
|
// 密码
|
|
31
32
|
password: "",
|
|
32
|
-
// 连接选项
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
},
|
|
40
|
-
// 重试配置
|
|
41
|
-
retry: {
|
|
42
|
-
maxAttempts: 3,
|
|
43
|
-
delayMS: 1000
|
|
44
|
-
}
|
|
45
|
-
}, config));
|
|
33
|
+
// 连接选项 (MongoDB驱动7.x版本支持的参数)
|
|
34
|
+
min_pool_size: 10,
|
|
35
|
+
max_pool_size: 100,
|
|
36
|
+
connect_timeout_ms: 10000,
|
|
37
|
+
server_selection_timeout_ms: 5000,
|
|
38
|
+
retry_writes: true
|
|
39
|
+
};
|
|
46
40
|
|
|
47
|
-
// 连接地址
|
|
48
|
-
this.url = null;
|
|
49
41
|
// 数据库连接器
|
|
50
42
|
this.conn = null;
|
|
51
43
|
// 操作的数据库
|
|
@@ -81,15 +73,15 @@ class MongoDB extends BaseService {
|
|
|
81
73
|
*/
|
|
82
74
|
MongoDB.prototype._validateConfig = function () {
|
|
83
75
|
if (!this.config.host || typeof this.config.host !== 'string') {
|
|
84
|
-
throw new
|
|
76
|
+
throw new TypeError('host必须是有效的字符串');
|
|
85
77
|
}
|
|
86
78
|
|
|
87
79
|
if (!Number.isInteger(this.config.port) || this.config.port < 1 || this.config.port > 65535) {
|
|
88
|
-
throw new
|
|
80
|
+
throw new TypeError('port必须是1-65535之间的整数');
|
|
89
81
|
}
|
|
90
82
|
|
|
91
83
|
if (!this.config.database || typeof this.config.database !== 'string') {
|
|
92
|
-
throw new
|
|
84
|
+
throw new TypeError('database必须是有效的字符串');
|
|
93
85
|
}
|
|
94
86
|
};
|
|
95
87
|
|
|
@@ -101,8 +93,8 @@ MongoDB.prototype._validateConfig = function () {
|
|
|
101
93
|
* @return {Promise} 操作结果
|
|
102
94
|
*/
|
|
103
95
|
MongoDB.prototype._withRetry = async function (operation, operationName) {
|
|
104
|
-
const maxAttempts =
|
|
105
|
-
const delayMS =
|
|
96
|
+
const maxAttempts = 3; // 固定重试次数,不再从配置读取
|
|
97
|
+
const delayMS = 1000; // 固定延迟时间,不再从配置读取
|
|
106
98
|
let lastError;
|
|
107
99
|
|
|
108
100
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
@@ -110,7 +102,7 @@ MongoDB.prototype._withRetry = async function (operation, operationName) {
|
|
|
110
102
|
return await operation();
|
|
111
103
|
} catch (error) {
|
|
112
104
|
lastError = error;
|
|
113
|
-
|
|
105
|
+
this.logger('error', `${operationName} 第${attempt}次尝试失败:`, error);
|
|
114
106
|
|
|
115
107
|
// 如果不是最后一次尝试,则等待后重试
|
|
116
108
|
if (attempt < maxAttempts) {
|
|
@@ -119,8 +111,8 @@ MongoDB.prototype._withRetry = async function (operation, operationName) {
|
|
|
119
111
|
}
|
|
120
112
|
}
|
|
121
113
|
|
|
122
|
-
//
|
|
123
|
-
|
|
114
|
+
// 所有重试都失败,触发错误事件
|
|
115
|
+
this.emit('error', lastError);
|
|
124
116
|
};
|
|
125
117
|
/**
|
|
126
118
|
* @description 确保数据库连接已建立
|
|
@@ -146,16 +138,16 @@ MongoDB.prototype._ensureConnected = async function () {
|
|
|
146
138
|
|
|
147
139
|
// 检查连接是否成功
|
|
148
140
|
if (this.db && this.db.collection) {
|
|
149
|
-
|
|
141
|
+
this.logger('debug', `[_ensureConnected] 连接成功,db对象存在,开始初始化collection,table=${this.table}`);
|
|
150
142
|
this.connected = true;
|
|
151
143
|
this.connectAttempts = 0;
|
|
152
144
|
|
|
153
145
|
// 保存collection引用到实例变量
|
|
154
146
|
try {
|
|
155
147
|
this.collection = this.db.collection(this.table);
|
|
156
|
-
|
|
148
|
+
this.logger('debug', `[_ensureConnected] 成功初始化collection: ${this.table}`);
|
|
157
149
|
} catch (err) {
|
|
158
|
-
|
|
150
|
+
this.logger('error', `[_ensureConnected] 初始化collection失败:`, err);
|
|
159
151
|
this.collection = null;
|
|
160
152
|
}
|
|
161
153
|
|
|
@@ -164,15 +156,14 @@ MongoDB.prototype._ensureConnected = async function () {
|
|
|
164
156
|
await this._ensureIndexes();
|
|
165
157
|
}
|
|
166
158
|
|
|
167
|
-
|
|
159
|
+
this.logger('info', `成功连接到数据库,表名: ${this.table}`);
|
|
168
160
|
} else {
|
|
169
|
-
|
|
161
|
+
this.logger('error', `[_ensureConnected] 连接失败,db对象为空或不具有collection方法`);
|
|
170
162
|
throw new Error('数据库连接失败,db对象为空');
|
|
171
163
|
}
|
|
172
164
|
}
|
|
173
165
|
} catch (error) {
|
|
174
|
-
|
|
175
|
-
error.message);
|
|
166
|
+
this.logger('error', `连接失败 (尝试 ${this.connectAttempts}/${this.maxConnectAttempts}):`, error);
|
|
176
167
|
|
|
177
168
|
// 重置连接Promise,允许下次重试
|
|
178
169
|
this.connectPromise = null;
|
|
@@ -182,8 +173,8 @@ MongoDB.prototype._ensureConnected = async function () {
|
|
|
182
173
|
throw error;
|
|
183
174
|
} else {
|
|
184
175
|
// 超过重试次数,记录严重错误
|
|
185
|
-
|
|
186
|
-
|
|
176
|
+
this.logger('error', '达到最大连接重试次数,连接失败');
|
|
177
|
+
this.emit('error', new Error('数据库连接失败,已达到最大重试次数'));
|
|
187
178
|
}
|
|
188
179
|
}
|
|
189
180
|
})();
|
|
@@ -216,7 +207,7 @@ MongoDB.prototype._ensureIndexes = async function () {
|
|
|
216
207
|
} catch (error) {
|
|
217
208
|
// 忽略索引已存在的错误
|
|
218
209
|
if (error.code !== 85) {
|
|
219
|
-
|
|
210
|
+
this.logger('error', '创建索引失败:', error);
|
|
220
211
|
}
|
|
221
212
|
}
|
|
222
213
|
};
|
|
@@ -224,18 +215,23 @@ MongoDB.prototype._ensureIndexes = async function () {
|
|
|
224
215
|
/**
|
|
225
216
|
* @description Redis兼容API - 获取缓存值
|
|
226
217
|
* @param {String} key 键名
|
|
227
|
-
* @return {Promise<any>} 返回键值,不存在返回
|
|
218
|
+
* @return {Promise<any>} 返回键值,不存在返回null
|
|
228
219
|
*/
|
|
229
220
|
MongoDB.prototype.get = async function (key) {
|
|
221
|
+
// 参数校验
|
|
222
|
+
if (typeof key !== 'string' || !key) {
|
|
223
|
+
throw new TypeError('key必须是有效的字符串');
|
|
224
|
+
}
|
|
225
|
+
|
|
230
226
|
try {
|
|
231
227
|
await this._ensureConnected();
|
|
232
228
|
const result = await this.findOne({
|
|
233
229
|
key: key
|
|
234
230
|
});
|
|
235
|
-
return result ? result.value :
|
|
231
|
+
return result ? result.value : null;
|
|
236
232
|
} catch (error) {
|
|
237
|
-
|
|
238
|
-
|
|
233
|
+
this.logger('error', '获取缓存失败:', error);
|
|
234
|
+
this.emit('error', error);
|
|
239
235
|
}
|
|
240
236
|
};
|
|
241
237
|
|
|
@@ -245,9 +241,14 @@ MongoDB.prototype.get = async function (key) {
|
|
|
245
241
|
* @return {Promise<Boolean>} 是否成功
|
|
246
242
|
*/
|
|
247
243
|
MongoDB.prototype.clear = async function (pattern) {
|
|
244
|
+
// 参数校验
|
|
245
|
+
if (pattern !== undefined && pattern !== null && typeof pattern !== 'string') {
|
|
246
|
+
throw new TypeError('pattern必须是有效的字符串');
|
|
247
|
+
}
|
|
248
|
+
|
|
248
249
|
try {
|
|
249
250
|
// 触发前置事件
|
|
250
|
-
this.emit('
|
|
251
|
+
this.emit('clear:before', {
|
|
251
252
|
pattern
|
|
252
253
|
});
|
|
253
254
|
|
|
@@ -261,7 +262,7 @@ MongoDB.prototype.clear = async function (pattern) {
|
|
|
261
262
|
$regex: regex
|
|
262
263
|
}
|
|
263
264
|
});
|
|
264
|
-
this.emit('
|
|
265
|
+
this.emit('clear:after', {
|
|
265
266
|
pattern,
|
|
266
267
|
result
|
|
267
268
|
});
|
|
@@ -269,17 +270,17 @@ MongoDB.prototype.clear = async function (pattern) {
|
|
|
269
270
|
} else {
|
|
270
271
|
// 清空所有数据,直接使用deleteMany操作
|
|
271
272
|
const result = await this.db.collection(this.table).deleteMany({});
|
|
272
|
-
this.emit('
|
|
273
|
+
this.emit('clear:after', {
|
|
273
274
|
result
|
|
274
275
|
});
|
|
275
276
|
return result.acknowledged;
|
|
276
277
|
}
|
|
277
278
|
} catch (error) {
|
|
278
|
-
this.emit('
|
|
279
|
+
this.emit('clear:error', {
|
|
279
280
|
error,
|
|
280
281
|
pattern
|
|
281
282
|
});
|
|
282
|
-
|
|
283
|
+
this.logger('error', '清空缓存失败:', error);
|
|
283
284
|
return false;
|
|
284
285
|
}
|
|
285
286
|
};
|
|
@@ -290,6 +291,11 @@ MongoDB.prototype.clear = async function (pattern) {
|
|
|
290
291
|
* @return {Promise<Array>} 键名数组
|
|
291
292
|
*/
|
|
292
293
|
MongoDB.prototype.keys = async function (pattern = '*') {
|
|
294
|
+
// 参数校验
|
|
295
|
+
if (typeof pattern !== 'string') {
|
|
296
|
+
throw new TypeError('pattern必须是有效的字符串');
|
|
297
|
+
}
|
|
298
|
+
|
|
293
299
|
try {
|
|
294
300
|
await this._ensureConnected();
|
|
295
301
|
let query = {};
|
|
@@ -307,7 +313,7 @@ MongoDB.prototype.keys = async function (pattern = '*') {
|
|
|
307
313
|
});
|
|
308
314
|
return results.map(item => item.key);
|
|
309
315
|
} catch (error) {
|
|
310
|
-
|
|
316
|
+
this.logger('error', '获取键列表失败:', error);
|
|
311
317
|
return [];
|
|
312
318
|
}
|
|
313
319
|
};
|
|
@@ -319,11 +325,12 @@ MongoDB.prototype.keys = async function (pattern = '*') {
|
|
|
319
325
|
* @return {Promise<Number|Boolean>} 不传seconds时返回剩余过期时间(-1表示无过期设置,-2表示已过期或不存在),传seconds时返回是否设置成功
|
|
320
326
|
*/
|
|
321
327
|
MongoDB.prototype.ttl = async function (key, seconds) {
|
|
328
|
+
// 参数验证
|
|
329
|
+
if (!key || typeof key !== 'string') {
|
|
330
|
+
throw new TypeError('key必须是非空字符串');
|
|
331
|
+
}
|
|
332
|
+
|
|
322
333
|
try {
|
|
323
|
-
// 参数验证
|
|
324
|
-
if (!key || typeof key !== 'string') {
|
|
325
|
-
return arguments.length === 1 ? -2 : false;
|
|
326
|
-
}
|
|
327
334
|
|
|
328
335
|
// 设置模式才需要触发事件
|
|
329
336
|
if (seconds !== undefined && seconds !== null) {
|
|
@@ -333,7 +340,7 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
333
340
|
seconds,
|
|
334
341
|
cancel: false
|
|
335
342
|
};
|
|
336
|
-
this.emit('
|
|
343
|
+
this.emit('ttl:before', beforeEventData);
|
|
337
344
|
|
|
338
345
|
if (beforeEventData.cancel) {
|
|
339
346
|
return false;
|
|
@@ -350,19 +357,19 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
350
357
|
|
|
351
358
|
// 直接尝试获取collection,使用实例的table属性
|
|
352
359
|
if (!this.collection && this.db && this.db.collection) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
360
|
+
this.logger('debug', `[ttl] 设置模式:直接获取collection, table=${this.table}`);
|
|
361
|
+
try {
|
|
362
|
+
this.collection = this.db.collection(this.table);
|
|
363
|
+
this.logger('debug', `[ttl] 设置模式:成功获取collection`);
|
|
357
364
|
} catch (err) {
|
|
358
|
-
|
|
365
|
+
this.logger('error', `[ttl] 设置模式:获取collection失败:`, err);
|
|
359
366
|
this.collection = null;
|
|
360
367
|
}
|
|
361
368
|
}
|
|
362
369
|
|
|
363
370
|
// 检查collection是否存在
|
|
364
371
|
if (!this.collection) {
|
|
365
|
-
this.emit('
|
|
372
|
+
this.emit('ttl:after', {
|
|
366
373
|
key: finalKey,
|
|
367
374
|
seconds: finalSeconds,
|
|
368
375
|
result: false
|
|
@@ -373,7 +380,7 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
373
380
|
// 检查键是否存在
|
|
374
381
|
const count = await this.collection.countDocuments({ key: finalKey });
|
|
375
382
|
if (count === 0) {
|
|
376
|
-
this.emit('
|
|
383
|
+
this.emit('ttl:after', {
|
|
377
384
|
key: finalKey,
|
|
378
385
|
seconds: finalSeconds,
|
|
379
386
|
result: false
|
|
@@ -400,7 +407,7 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
400
407
|
{ upsert: false }
|
|
401
408
|
);
|
|
402
409
|
|
|
403
|
-
this.emit('
|
|
410
|
+
this.emit('ttl:after', {
|
|
404
411
|
key: finalKey,
|
|
405
412
|
seconds: finalSeconds,
|
|
406
413
|
result: true
|
|
@@ -418,12 +425,12 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
418
425
|
|
|
419
426
|
// 直接尝试获取collection,使用实例的table属性
|
|
420
427
|
if (!this.collection && this.db && this.db.collection) {
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
428
|
+
this.logger('debug', `[ttl] 直接获取collection, table=${this.table}`);
|
|
429
|
+
try {
|
|
430
|
+
this.collection = this.db.collection(this.table);
|
|
431
|
+
this.logger('debug', `[ttl] 成功获取collection`);
|
|
425
432
|
} catch (err) {
|
|
426
|
-
|
|
433
|
+
this.logger('error', `[ttl] 获取collection失败:`, err);
|
|
427
434
|
this.collection = null;
|
|
428
435
|
}
|
|
429
436
|
}
|
|
@@ -434,19 +441,19 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
434
441
|
}
|
|
435
442
|
|
|
436
443
|
// 查询键是否存在及过期时间
|
|
437
|
-
|
|
438
|
-
|
|
444
|
+
const item = await this.collection.findOne({ key });
|
|
445
|
+
this.logger('debug', `[ttl] 查询键结果: item=${JSON.stringify(item)}`);
|
|
439
446
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
447
|
+
if (!item) {
|
|
448
|
+
// 键不存在返回-2
|
|
449
|
+
this.logger('debug', `[ttl] 键 ${key} 不存在,返回-2`);
|
|
450
|
+
return -2;
|
|
451
|
+
}
|
|
445
452
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
453
|
+
if (!item.expire_at) {
|
|
454
|
+
// 没有过期时间返回-1
|
|
455
|
+
this.logger('debug', `[ttl] 键 ${key} 没有过期时间,返回-1`);
|
|
456
|
+
return -1;
|
|
450
457
|
}
|
|
451
458
|
|
|
452
459
|
// 计算剩余过期时间
|
|
@@ -463,8 +470,8 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
463
470
|
return remainingSeconds;
|
|
464
471
|
}
|
|
465
472
|
} catch (error) {
|
|
466
|
-
this.emit('
|
|
467
|
-
|
|
473
|
+
this.emit('ttl:error', { key, seconds, error });
|
|
474
|
+
this.logger('error', `[ttl] 操作失败:`, error);
|
|
468
475
|
return arguments.length === 1 ? -2 : false;
|
|
469
476
|
}
|
|
470
477
|
};
|
|
@@ -475,18 +482,19 @@ MongoDB.prototype.ttl = async function (key, seconds) {
|
|
|
475
482
|
* @return {Promise<boolean>} 移除成功返回true,键不存在或没有过期时间返回false
|
|
476
483
|
*/
|
|
477
484
|
MongoDB.prototype.persist = async function (key) {
|
|
485
|
+
// 参数验证
|
|
486
|
+
if (!key || typeof key !== 'string') {
|
|
487
|
+
throw new TypeError('key必须是非空字符串');
|
|
488
|
+
}
|
|
489
|
+
|
|
478
490
|
try {
|
|
479
|
-
// 参数验证
|
|
480
|
-
if (!key || typeof key !== 'string') {
|
|
481
|
-
return false;
|
|
482
|
-
}
|
|
483
491
|
|
|
484
492
|
// 触发前置事件
|
|
485
493
|
const beforeEventData = {
|
|
486
494
|
key,
|
|
487
495
|
cancel: false
|
|
488
496
|
};
|
|
489
|
-
this.emit('
|
|
497
|
+
this.emit('persist:before', beforeEventData);
|
|
490
498
|
|
|
491
499
|
if (beforeEventData.cancel) {
|
|
492
500
|
return false;
|
|
@@ -501,20 +509,20 @@ MongoDB.prototype.persist = async function (key) {
|
|
|
501
509
|
|
|
502
510
|
// 直接尝试获取collection,不依赖_ensureConnected的复杂逻辑
|
|
503
511
|
if (!this.collection && this.db && this.db.collection) {
|
|
504
|
-
|
|
512
|
+
this.logger('debug', `[persist] 直接获取collection, table=${this.table}`);
|
|
505
513
|
try {
|
|
506
514
|
this.collection = this.db.collection(this.table);
|
|
507
|
-
|
|
515
|
+
this.logger('debug', `[persist] 成功获取collection`);
|
|
508
516
|
} catch (err) {
|
|
509
|
-
|
|
517
|
+
this.logger('error', `[persist] 获取collection失败:`, err);
|
|
510
518
|
this.collection = null;
|
|
511
519
|
}
|
|
512
520
|
}
|
|
513
521
|
|
|
514
522
|
// 再次检查collection
|
|
515
523
|
if (!this.collection) {
|
|
516
|
-
|
|
517
|
-
this.emit('
|
|
524
|
+
this.logger('error', 'persist: collection is undefined');
|
|
525
|
+
this.emit('persist:error', {
|
|
518
526
|
key: finalKey,
|
|
519
527
|
error: new Error('collection is undefined')
|
|
520
528
|
});
|
|
@@ -525,7 +533,7 @@ MongoDB.prototype.persist = async function (key) {
|
|
|
525
533
|
const item = await this.collection.findOne({ key: finalKey });
|
|
526
534
|
if (!item) {
|
|
527
535
|
// 键不存在返回false
|
|
528
|
-
this.emit('
|
|
536
|
+
this.emit('persist:after', {
|
|
529
537
|
key: finalKey,
|
|
530
538
|
success: false
|
|
531
539
|
});
|
|
@@ -534,7 +542,7 @@ MongoDB.prototype.persist = async function (key) {
|
|
|
534
542
|
|
|
535
543
|
// 如果没有过期时间,直接返回true
|
|
536
544
|
if (!item.expire_at) {
|
|
537
|
-
this.emit('
|
|
545
|
+
this.emit('persist:after', {
|
|
538
546
|
key: finalKey,
|
|
539
547
|
success: true
|
|
540
548
|
});
|
|
@@ -552,14 +560,14 @@ MongoDB.prototype.persist = async function (key) {
|
|
|
552
560
|
const success = result.modifiedCount > 0;
|
|
553
561
|
|
|
554
562
|
// 触发后置事件
|
|
555
|
-
this.emit('
|
|
563
|
+
this.emit('persist:after', {
|
|
556
564
|
key: finalKey,
|
|
557
565
|
success: success
|
|
558
566
|
});
|
|
559
567
|
return success;
|
|
560
568
|
} catch (error) {
|
|
561
|
-
|
|
562
|
-
this.emit('
|
|
569
|
+
this.logger('error', 'persist error:', error);
|
|
570
|
+
this.emit('persist:error', {
|
|
563
571
|
key,
|
|
564
572
|
error
|
|
565
573
|
});
|
|
@@ -597,7 +605,7 @@ MongoDB.prototype._add = async function (key, value, expire) {
|
|
|
597
605
|
}
|
|
598
606
|
return true;
|
|
599
607
|
} catch (error) {
|
|
600
|
-
|
|
608
|
+
this.logger('error', '添加缓存失败:', error);
|
|
601
609
|
return false;
|
|
602
610
|
}
|
|
603
611
|
};
|
|
@@ -618,11 +626,11 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
618
626
|
ttl: seconds,
|
|
619
627
|
cancel: false
|
|
620
628
|
};
|
|
621
|
-
this.emit('
|
|
629
|
+
this.emit('add:before', beforeEventData);
|
|
622
630
|
|
|
623
631
|
// 如果事件处理器标记为取消,则返回false
|
|
624
632
|
if (beforeEventData.cancel) {
|
|
625
|
-
|
|
633
|
+
this.logger('debug', `add操作被事件处理器取消 [${key}]`);
|
|
626
634
|
return false;
|
|
627
635
|
}
|
|
628
636
|
|
|
@@ -641,7 +649,7 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
641
649
|
});
|
|
642
650
|
if (existing) {
|
|
643
651
|
// 键已存在,返回false
|
|
644
|
-
this.emit('
|
|
652
|
+
this.emit('add:after', {
|
|
645
653
|
key: finalKey,
|
|
646
654
|
value: finalValue,
|
|
647
655
|
ttl: finalSeconds,
|
|
@@ -663,7 +671,7 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
663
671
|
await this.addObj(data);
|
|
664
672
|
|
|
665
673
|
// 触发后置事件
|
|
666
|
-
this.emit('
|
|
674
|
+
this.emit('add:after', {
|
|
667
675
|
key: finalKey,
|
|
668
676
|
value: finalValue,
|
|
669
677
|
ttl: finalSeconds,
|
|
@@ -671,9 +679,9 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
671
679
|
});
|
|
672
680
|
return true;
|
|
673
681
|
} catch (error) {
|
|
674
|
-
|
|
682
|
+
this.logger('error', `添加缓存失败 [${key}]:`, error);
|
|
675
683
|
// 触发错误事件
|
|
676
|
-
this.emit('
|
|
684
|
+
this.emit('add:error', {
|
|
677
685
|
key,
|
|
678
686
|
value,
|
|
679
687
|
ttl: seconds,
|
|
@@ -706,8 +714,8 @@ MongoDB.prototype._addNum = async function (key, value = 1) {
|
|
|
706
714
|
await this._add(key, newValue);
|
|
707
715
|
return newValue;
|
|
708
716
|
} catch (error) {
|
|
709
|
-
|
|
710
|
-
return
|
|
717
|
+
this.logger('error', '增加整数值失败:', error);
|
|
718
|
+
return false;
|
|
711
719
|
}
|
|
712
720
|
};
|
|
713
721
|
|
|
@@ -724,6 +732,11 @@ MongoDB.prototype._addNum = async function (key, value = 1) {
|
|
|
724
732
|
* @return {Promise<Number>} 增加后的值
|
|
725
733
|
*/
|
|
726
734
|
MongoDB.prototype.addInt = async function (key, value = 1, seconds = 0) {
|
|
735
|
+
// 参数验证
|
|
736
|
+
if (!key || typeof key !== 'string') {
|
|
737
|
+
throw new TypeError('key必须是非空字符串');
|
|
738
|
+
}
|
|
739
|
+
|
|
727
740
|
try {
|
|
728
741
|
// 触发前置事件,允许修改或阻止操作
|
|
729
742
|
const beforeEventData = {
|
|
@@ -732,11 +745,11 @@ MongoDB.prototype.addInt = async function (key, value = 1, seconds = 0) {
|
|
|
732
745
|
seconds,
|
|
733
746
|
cancel: false
|
|
734
747
|
};
|
|
735
|
-
this.emit('
|
|
748
|
+
this.emit('addInt:before', beforeEventData);
|
|
736
749
|
|
|
737
750
|
// 如果事件处理器标记为取消,则返回默认值
|
|
738
751
|
if (beforeEventData.cancel) {
|
|
739
|
-
|
|
752
|
+
this.logger('debug', 'addInt操作被事件处理器取消');
|
|
740
753
|
return 0;
|
|
741
754
|
}
|
|
742
755
|
|
|
@@ -747,12 +760,6 @@ MongoDB.prototype.addInt = async function (key, value = 1, seconds = 0) {
|
|
|
747
760
|
seconds: finalSeconds
|
|
748
761
|
} = beforeEventData;
|
|
749
762
|
|
|
750
|
-
// 参数验证
|
|
751
|
-
if (!finalKey || typeof finalKey !== 'string') {
|
|
752
|
-
$.log.warn('[MongoDB] addInt: key必须是非空字符串');
|
|
753
|
-
return 0;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
763
|
finalValue = Number(finalValue) || 0;
|
|
757
764
|
|
|
758
765
|
await this._ensureConnected();
|
|
@@ -771,7 +778,7 @@ MongoDB.prototype.addInt = async function (key, value = 1, seconds = 0) {
|
|
|
771
778
|
await this._add(finalKey, newValue, finalSeconds);
|
|
772
779
|
|
|
773
780
|
// 触发后置事件
|
|
774
|
-
this.emit('
|
|
781
|
+
this.emit('addInt:after', {
|
|
775
782
|
key: finalKey,
|
|
776
783
|
value: finalValue,
|
|
777
784
|
seconds: finalSeconds,
|
|
@@ -781,13 +788,13 @@ MongoDB.prototype.addInt = async function (key, value = 1, seconds = 0) {
|
|
|
781
788
|
return newValue;
|
|
782
789
|
} catch (error) {
|
|
783
790
|
// 触发错误事件
|
|
784
|
-
this.emit('
|
|
791
|
+
this.emit('addInt:error', {
|
|
785
792
|
key,
|
|
786
793
|
value,
|
|
787
794
|
seconds,
|
|
788
795
|
error
|
|
789
796
|
});
|
|
790
|
-
|
|
797
|
+
this.logger('error', '增加整数值失败:', error);
|
|
791
798
|
// 与CacheBase保持一致,错误时返回默认值而不是抛出异常
|
|
792
799
|
return 0;
|
|
793
800
|
}
|
|
@@ -800,6 +807,11 @@ MongoDB.prototype.addInt = async function (key, value = 1, seconds = 0) {
|
|
|
800
807
|
* @return {Promise<Number>} 增加后的值
|
|
801
808
|
*/
|
|
802
809
|
MongoDB.prototype.addFloat = async function (key, value = 1.0, seconds = 0) {
|
|
810
|
+
// 参数验证
|
|
811
|
+
if (!key || typeof key !== 'string') {
|
|
812
|
+
throw new TypeError('key必须是非空字符串');
|
|
813
|
+
}
|
|
814
|
+
|
|
803
815
|
try {
|
|
804
816
|
// 触发前置事件,允许修改或阻止操作
|
|
805
817
|
const beforeEventData = {
|
|
@@ -808,11 +820,11 @@ MongoDB.prototype.addFloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
808
820
|
seconds,
|
|
809
821
|
cancel: false
|
|
810
822
|
};
|
|
811
|
-
this.emit('
|
|
823
|
+
this.emit('addFloat:before', beforeEventData);
|
|
812
824
|
|
|
813
825
|
// 如果事件处理器标记为取消,则返回默认值
|
|
814
826
|
if (beforeEventData.cancel) {
|
|
815
|
-
|
|
827
|
+
this.logger('debug', 'addFloat操作被事件处理器取消');
|
|
816
828
|
return 0.0;
|
|
817
829
|
}
|
|
818
830
|
|
|
@@ -823,12 +835,6 @@ MongoDB.prototype.addFloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
823
835
|
seconds: finalSeconds
|
|
824
836
|
} = beforeEventData;
|
|
825
837
|
|
|
826
|
-
// 参数验证
|
|
827
|
-
if (!finalKey || typeof finalKey !== 'string') {
|
|
828
|
-
$.log.warn('[MongoDB] addFloat: key必须是非空字符串');
|
|
829
|
-
return 0.0;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
838
|
finalValue = Number(finalValue) || 0.0;
|
|
833
839
|
|
|
834
840
|
await this._ensureConnected();
|
|
@@ -847,7 +853,7 @@ MongoDB.prototype.addFloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
847
853
|
await this._add(finalKey, newValue, finalSeconds);
|
|
848
854
|
|
|
849
855
|
// 触发后置事件
|
|
850
|
-
this.emit('
|
|
856
|
+
this.emit('addFloat:after', {
|
|
851
857
|
key: finalKey,
|
|
852
858
|
value: finalValue,
|
|
853
859
|
seconds: finalSeconds,
|
|
@@ -857,13 +863,13 @@ MongoDB.prototype.addFloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
857
863
|
return newValue;
|
|
858
864
|
} catch (error) {
|
|
859
865
|
// 触发错误事件
|
|
860
|
-
this.emit('
|
|
866
|
+
this.emit('addFloat:error', {
|
|
861
867
|
key,
|
|
862
868
|
value,
|
|
863
869
|
seconds,
|
|
864
870
|
error
|
|
865
871
|
});
|
|
866
|
-
|
|
872
|
+
this.logger('error', '增加浮点数值失败:', error);
|
|
867
873
|
// 与CacheBase保持一致,错误时返回默认值而不是抛出异常
|
|
868
874
|
return 0.0;
|
|
869
875
|
}
|
|
@@ -876,22 +882,22 @@ MongoDB.prototype.addFloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
876
882
|
* @return {Promise<Number>} 添加后的字符串长度
|
|
877
883
|
*/
|
|
878
884
|
MongoDB.prototype.addStr = async function (key, value) {
|
|
885
|
+
// 参数验证
|
|
886
|
+
if (!key || typeof key !== 'string') {
|
|
887
|
+
throw new TypeError('key必须是非空字符串');
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (value === undefined || value === null) {
|
|
891
|
+
value = '';
|
|
892
|
+
}
|
|
893
|
+
|
|
879
894
|
try {
|
|
880
895
|
// 触发前置事件
|
|
881
|
-
this.emit('
|
|
896
|
+
this.emit('addStr:before', {
|
|
882
897
|
key,
|
|
883
898
|
value
|
|
884
899
|
});
|
|
885
900
|
|
|
886
|
-
// 参数验证
|
|
887
|
-
if (!key || typeof key !== 'string') {
|
|
888
|
-
throw new Error('key必须是非空字符串');
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
if (value === undefined || value === null) {
|
|
892
|
-
value = '';
|
|
893
|
-
}
|
|
894
|
-
|
|
895
901
|
await this._ensureConnected();
|
|
896
902
|
// 获取当前值
|
|
897
903
|
const item = await this.findOne({
|
|
@@ -903,7 +909,7 @@ MongoDB.prototype.addStr = async function (key, value) {
|
|
|
903
909
|
await this._add(key, newValue);
|
|
904
910
|
|
|
905
911
|
// 触发后置事件
|
|
906
|
-
this.emit('
|
|
912
|
+
this.emit('addStr:after', {
|
|
907
913
|
key,
|
|
908
914
|
value,
|
|
909
915
|
result: newValue.length
|
|
@@ -912,12 +918,12 @@ MongoDB.prototype.addStr = async function (key, value) {
|
|
|
912
918
|
return newValue.length;
|
|
913
919
|
} catch (error) {
|
|
914
920
|
// 触发错误事件
|
|
915
|
-
this.emit('
|
|
921
|
+
this.emit('addStr:error', {
|
|
916
922
|
key,
|
|
917
923
|
value,
|
|
918
924
|
error
|
|
919
925
|
});
|
|
920
|
-
|
|
926
|
+
this.logger('error', '添加字符串失败:', error);
|
|
921
927
|
return 0;
|
|
922
928
|
}
|
|
923
929
|
};
|
|
@@ -954,7 +960,7 @@ MongoDB.prototype.sort = async function (key, options = {}) {
|
|
|
954
960
|
|
|
955
961
|
return sorted;
|
|
956
962
|
} catch (error) {
|
|
957
|
-
|
|
963
|
+
this.logger('error', '排序失败:', error);
|
|
958
964
|
return [];
|
|
959
965
|
}
|
|
960
966
|
};
|
|
@@ -967,6 +973,14 @@ MongoDB.prototype.sort = async function (key, options = {}) {
|
|
|
967
973
|
* @return {Promise<number>} 返回1表示新建字段,0表示更新字段
|
|
968
974
|
*/
|
|
969
975
|
MongoDB.prototype.hset = async function (key, field, value) {
|
|
976
|
+
// 参数校验
|
|
977
|
+
if (typeof key !== 'string' || !key) {
|
|
978
|
+
throw new TypeError('key必须是有效的字符串');
|
|
979
|
+
}
|
|
980
|
+
if (typeof field !== 'string' || !field) {
|
|
981
|
+
throw new TypeError('field必须是有效的字符串');
|
|
982
|
+
}
|
|
983
|
+
|
|
970
984
|
try {
|
|
971
985
|
await this._ensureConnected();
|
|
972
986
|
const item = await this.findOne({
|
|
@@ -978,9 +992,9 @@ MongoDB.prototype.hset = async function (key, field, value) {
|
|
|
978
992
|
const isNewField = !hash.hasOwnProperty(field);
|
|
979
993
|
hash[field] = value;
|
|
980
994
|
await this._add(key, hash);
|
|
981
|
-
return
|
|
995
|
+
return true; // hset操作成功返回true
|
|
982
996
|
} catch (error) {
|
|
983
|
-
|
|
997
|
+
this.logger('error', '哈希表设置失败:', error);
|
|
984
998
|
throw error;
|
|
985
999
|
}
|
|
986
1000
|
};
|
|
@@ -992,6 +1006,14 @@ MongoDB.prototype.hset = async function (key, field, value) {
|
|
|
992
1006
|
* @return {Promise<any>} 返回字段值,不存在返回undefined
|
|
993
1007
|
*/
|
|
994
1008
|
MongoDB.prototype.hget = async function (key, field) {
|
|
1009
|
+
// 参数校验
|
|
1010
|
+
if (typeof key !== 'string' || !key) {
|
|
1011
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1012
|
+
}
|
|
1013
|
+
if (typeof field !== 'string' || !field) {
|
|
1014
|
+
throw new TypeError('field必须是有效的字符串');
|
|
1015
|
+
}
|
|
1016
|
+
|
|
995
1017
|
try {
|
|
996
1018
|
await this._ensureConnected();
|
|
997
1019
|
const item = await this.findOne({
|
|
@@ -1002,8 +1024,8 @@ MongoDB.prototype.hget = async function (key, field) {
|
|
|
1002
1024
|
}
|
|
1003
1025
|
return item.value[field] !== undefined ? item.value[field] : undefined;
|
|
1004
1026
|
} catch (error) {
|
|
1005
|
-
|
|
1006
|
-
|
|
1027
|
+
this.logger('error', '哈希表获取失败:', error);
|
|
1028
|
+
return null; // 与Redis保持一致,错误时返回null
|
|
1007
1029
|
}
|
|
1008
1030
|
};
|
|
1009
1031
|
|
|
@@ -1013,6 +1035,11 @@ MongoDB.prototype.hget = async function (key, field) {
|
|
|
1013
1035
|
* @return {Promise<Object>} 哈希表对象
|
|
1014
1036
|
*/
|
|
1015
1037
|
MongoDB.prototype.hgetall = async function (key) {
|
|
1038
|
+
// 参数校验
|
|
1039
|
+
if (typeof key !== 'string' || !key) {
|
|
1040
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1016
1043
|
try {
|
|
1017
1044
|
const item = await this.findOne({
|
|
1018
1045
|
key: key
|
|
@@ -1022,7 +1049,7 @@ MongoDB.prototype.hgetall = async function (key) {
|
|
|
1022
1049
|
}
|
|
1023
1050
|
return item.value;
|
|
1024
1051
|
} catch (error) {
|
|
1025
|
-
|
|
1052
|
+
this.logger('error', '哈希表获取全部失败:', error);
|
|
1026
1053
|
return {};
|
|
1027
1054
|
}
|
|
1028
1055
|
};
|
|
@@ -1034,12 +1061,15 @@ MongoDB.prototype.hgetall = async function (key) {
|
|
|
1034
1061
|
* @return {Promise<boolean>} 返回true表示成功删除,false表示未删除
|
|
1035
1062
|
*/
|
|
1036
1063
|
MongoDB.prototype.hdel = async function (key, fields) {
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1064
|
+
// 参数校验
|
|
1065
|
+
if (typeof key !== 'string' || !key) {
|
|
1066
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1067
|
+
}
|
|
1068
|
+
if (!fields || (typeof fields !== 'string' && !Array.isArray(fields))) {
|
|
1069
|
+
throw new TypeError('fields必须是字符串或字符串数组');
|
|
1070
|
+
}
|
|
1042
1071
|
|
|
1072
|
+
try {
|
|
1043
1073
|
// 统一将fields转换为数组格式
|
|
1044
1074
|
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
1045
1075
|
if (fieldArray.length === 0) {
|
|
@@ -1079,7 +1109,7 @@ MongoDB.prototype.hdel = async function (key, fields) {
|
|
|
1079
1109
|
|
|
1080
1110
|
return deletedCount;
|
|
1081
1111
|
} catch (error) {
|
|
1082
|
-
|
|
1112
|
+
this.logger('error', 'hdel操作失败:', error);
|
|
1083
1113
|
return 0;
|
|
1084
1114
|
}
|
|
1085
1115
|
};
|
|
@@ -1090,13 +1120,18 @@ MongoDB.prototype.hdel = async function (key, fields) {
|
|
|
1090
1120
|
* @return {Promise<Boolean>} 是否存在
|
|
1091
1121
|
*/
|
|
1092
1122
|
MongoDB.prototype.has = async function (key) {
|
|
1123
|
+
// 参数校验
|
|
1124
|
+
if (typeof key !== 'string' || !key) {
|
|
1125
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1093
1128
|
try {
|
|
1094
1129
|
const result = await this.findOne({
|
|
1095
1130
|
key: key
|
|
1096
1131
|
});
|
|
1097
1132
|
return result !== null;
|
|
1098
1133
|
} catch (error) {
|
|
1099
|
-
|
|
1134
|
+
this.logger('error', '[has] 检查键是否存在失败:', error);
|
|
1100
1135
|
throw error;
|
|
1101
1136
|
}
|
|
1102
1137
|
};
|
|
@@ -1118,11 +1153,11 @@ MongoDB.prototype.expire = async function (key, seconds) {
|
|
|
1118
1153
|
seconds,
|
|
1119
1154
|
cancel: false
|
|
1120
1155
|
};
|
|
1121
|
-
this.emit('
|
|
1156
|
+
this.emit('expire:before', beforeEventData);
|
|
1122
1157
|
|
|
1123
1158
|
// 如果事件处理器标记为取消,则返回默认值
|
|
1124
1159
|
if (beforeEventData.cancel) {
|
|
1125
|
-
|
|
1160
|
+
this.logger('debug', 'expire操作被事件处理器取消');
|
|
1126
1161
|
return false;
|
|
1127
1162
|
}
|
|
1128
1163
|
|
|
@@ -1136,7 +1171,7 @@ MongoDB.prototype.expire = async function (key, seconds) {
|
|
|
1136
1171
|
const result = await this.ttl(finalKey, finalSeconds);
|
|
1137
1172
|
|
|
1138
1173
|
// 触发后置事件
|
|
1139
|
-
this.emit('
|
|
1174
|
+
this.emit('expire:after', {
|
|
1140
1175
|
key: finalKey,
|
|
1141
1176
|
seconds: finalSeconds,
|
|
1142
1177
|
result
|
|
@@ -1146,10 +1181,10 @@ MongoDB.prototype.expire = async function (key, seconds) {
|
|
|
1146
1181
|
return result === true || (typeof result === 'number' && result >= -2);
|
|
1147
1182
|
} catch (error) {
|
|
1148
1183
|
// 记录错误日志
|
|
1149
|
-
|
|
1184
|
+
this.logger('error', 'expire方法执行错误', { error: error.message, key, seconds });
|
|
1150
1185
|
|
|
1151
1186
|
// 触发错误事件
|
|
1152
|
-
this.emit('
|
|
1187
|
+
this.emit('expire:error', {
|
|
1153
1188
|
key,
|
|
1154
1189
|
seconds,
|
|
1155
1190
|
error
|
|
@@ -1172,11 +1207,11 @@ MongoDB.prototype.incr = async function (key, seconds = 0) {
|
|
|
1172
1207
|
seconds,
|
|
1173
1208
|
cancel: false
|
|
1174
1209
|
};
|
|
1175
|
-
this.emit('
|
|
1210
|
+
this.emit('incr:before', beforeEventData);
|
|
1176
1211
|
|
|
1177
1212
|
// 如果事件处理器标记为取消,则返回默认值
|
|
1178
1213
|
if (beforeEventData.cancel) {
|
|
1179
|
-
|
|
1214
|
+
this.logger('debug', 'incr操作被事件处理器取消');
|
|
1180
1215
|
return 0;
|
|
1181
1216
|
}
|
|
1182
1217
|
|
|
@@ -1187,9 +1222,8 @@ MongoDB.prototype.incr = async function (key, seconds = 0) {
|
|
|
1187
1222
|
} = beforeEventData;
|
|
1188
1223
|
|
|
1189
1224
|
// 参数验证
|
|
1190
|
-
if (
|
|
1191
|
-
|
|
1192
|
-
return 0;
|
|
1225
|
+
if (typeof finalKey !== 'string' || !finalKey) {
|
|
1226
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1193
1227
|
}
|
|
1194
1228
|
|
|
1195
1229
|
await this._ensureConnected();
|
|
@@ -1197,7 +1231,7 @@ MongoDB.prototype.incr = async function (key, seconds = 0) {
|
|
|
1197
1231
|
const returnResult = result !== undefined ? result : 0;
|
|
1198
1232
|
|
|
1199
1233
|
// 触发后置事件
|
|
1200
|
-
this.emit('
|
|
1234
|
+
this.emit('incr:after', {
|
|
1201
1235
|
key: finalKey,
|
|
1202
1236
|
seconds: finalSeconds,
|
|
1203
1237
|
result: returnResult,
|
|
@@ -1207,12 +1241,12 @@ MongoDB.prototype.incr = async function (key, seconds = 0) {
|
|
|
1207
1241
|
return returnResult;
|
|
1208
1242
|
} catch (error) {
|
|
1209
1243
|
// 触发错误事件
|
|
1210
|
-
this.emit('
|
|
1244
|
+
this.emit('incr:error', {
|
|
1211
1245
|
key,
|
|
1212
1246
|
seconds,
|
|
1213
1247
|
error
|
|
1214
1248
|
});
|
|
1215
|
-
|
|
1249
|
+
this.logger('error', '递增操作失败:', error);
|
|
1216
1250
|
return 0;
|
|
1217
1251
|
}
|
|
1218
1252
|
};
|
|
@@ -1230,11 +1264,11 @@ MongoDB.prototype.decr = async function (key, seconds = 0) {
|
|
|
1230
1264
|
seconds,
|
|
1231
1265
|
cancel: false
|
|
1232
1266
|
};
|
|
1233
|
-
this.emit('
|
|
1267
|
+
this.emit('decr:before', beforeEventData);
|
|
1234
1268
|
|
|
1235
1269
|
// 如果事件处理器标记为取消,则返回默认值
|
|
1236
1270
|
if (beforeEventData.cancel) {
|
|
1237
|
-
|
|
1271
|
+
this.logger('debug', 'decr操作被事件处理器取消');
|
|
1238
1272
|
return 0;
|
|
1239
1273
|
}
|
|
1240
1274
|
|
|
@@ -1245,9 +1279,8 @@ MongoDB.prototype.decr = async function (key, seconds = 0) {
|
|
|
1245
1279
|
} = beforeEventData;
|
|
1246
1280
|
|
|
1247
1281
|
// 参数验证
|
|
1248
|
-
if (
|
|
1249
|
-
|
|
1250
|
-
return 0;
|
|
1282
|
+
if (typeof finalKey !== 'string' || !finalKey) {
|
|
1283
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1251
1284
|
}
|
|
1252
1285
|
|
|
1253
1286
|
await this._ensureConnected();
|
|
@@ -1255,7 +1288,7 @@ MongoDB.prototype.decr = async function (key, seconds = 0) {
|
|
|
1255
1288
|
const returnResult = result !== undefined ? result : 0;
|
|
1256
1289
|
|
|
1257
1290
|
// 触发后置事件
|
|
1258
|
-
this.emit('
|
|
1291
|
+
this.emit('decr:after', {
|
|
1259
1292
|
key: finalKey,
|
|
1260
1293
|
seconds: finalSeconds,
|
|
1261
1294
|
result: returnResult,
|
|
@@ -1265,12 +1298,12 @@ MongoDB.prototype.decr = async function (key, seconds = 0) {
|
|
|
1265
1298
|
return returnResult;
|
|
1266
1299
|
} catch (error) {
|
|
1267
1300
|
// 触发错误事件
|
|
1268
|
-
this.emit('
|
|
1301
|
+
this.emit('decr:error', {
|
|
1269
1302
|
key,
|
|
1270
1303
|
seconds,
|
|
1271
1304
|
error
|
|
1272
1305
|
});
|
|
1273
|
-
|
|
1306
|
+
this.logger('error', '递减操作失败:', error);
|
|
1274
1307
|
return 0;
|
|
1275
1308
|
}
|
|
1276
1309
|
};
|
|
@@ -1290,11 +1323,11 @@ MongoDB.prototype.incrby = async function (key, value = 1, seconds = 0) {
|
|
|
1290
1323
|
seconds,
|
|
1291
1324
|
cancel: false
|
|
1292
1325
|
};
|
|
1293
|
-
this.emit('
|
|
1326
|
+
this.emit('incrby:before', beforeEventData);
|
|
1294
1327
|
|
|
1295
1328
|
// 如果事件处理器标记为取消,则返回默认值
|
|
1296
1329
|
if (beforeEventData.cancel) {
|
|
1297
|
-
|
|
1330
|
+
this.logger('debug', 'incrby操作被事件处理器取消');
|
|
1298
1331
|
return 0;
|
|
1299
1332
|
}
|
|
1300
1333
|
|
|
@@ -1306,9 +1339,8 @@ MongoDB.prototype.incrby = async function (key, value = 1, seconds = 0) {
|
|
|
1306
1339
|
} = beforeEventData;
|
|
1307
1340
|
|
|
1308
1341
|
// 参数验证
|
|
1309
|
-
if (
|
|
1310
|
-
|
|
1311
|
-
return 0;
|
|
1342
|
+
if (typeof finalKey !== 'string' || !finalKey) {
|
|
1343
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1312
1344
|
}
|
|
1313
1345
|
|
|
1314
1346
|
// 确保value是数字
|
|
@@ -1319,7 +1351,7 @@ MongoDB.prototype.incrby = async function (key, value = 1, seconds = 0) {
|
|
|
1319
1351
|
const returnResult = result !== undefined ? result : 0;
|
|
1320
1352
|
|
|
1321
1353
|
// 触发后置事件
|
|
1322
|
-
this.emit('
|
|
1354
|
+
this.emit('incrby:after', {
|
|
1323
1355
|
key: finalKey,
|
|
1324
1356
|
value: finalValue,
|
|
1325
1357
|
seconds: finalSeconds,
|
|
@@ -1330,13 +1362,13 @@ MongoDB.prototype.incrby = async function (key, value = 1, seconds = 0) {
|
|
|
1330
1362
|
return returnResult;
|
|
1331
1363
|
} catch (error) {
|
|
1332
1364
|
// 触发错误事件
|
|
1333
|
-
this.emit('
|
|
1365
|
+
this.emit('incrby:error', {
|
|
1334
1366
|
key,
|
|
1335
1367
|
value,
|
|
1336
1368
|
seconds,
|
|
1337
1369
|
error
|
|
1338
1370
|
});
|
|
1339
|
-
|
|
1371
|
+
this.logger('error', '递增操作失败:', error);
|
|
1340
1372
|
return 0;
|
|
1341
1373
|
}
|
|
1342
1374
|
};
|
|
@@ -1356,11 +1388,11 @@ MongoDB.prototype.decrby = async function (key, value = 1, seconds = 0) {
|
|
|
1356
1388
|
seconds,
|
|
1357
1389
|
cancel: false
|
|
1358
1390
|
};
|
|
1359
|
-
this.emit('
|
|
1391
|
+
this.emit('decrby:before', beforeEventData);
|
|
1360
1392
|
|
|
1361
1393
|
// 如果事件处理器标记为取消,则返回默认值
|
|
1362
1394
|
if (beforeEventData.cancel) {
|
|
1363
|
-
|
|
1395
|
+
this.logger('debug', 'decrby操作被事件处理器取消');
|
|
1364
1396
|
return 0;
|
|
1365
1397
|
}
|
|
1366
1398
|
|
|
@@ -1372,9 +1404,8 @@ MongoDB.prototype.decrby = async function (key, value = 1, seconds = 0) {
|
|
|
1372
1404
|
} = beforeEventData;
|
|
1373
1405
|
|
|
1374
1406
|
// 参数验证
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1377
|
-
return 0;
|
|
1407
|
+
if (typeof finalKey !== 'string' || !finalKey) {
|
|
1408
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1378
1409
|
}
|
|
1379
1410
|
|
|
1380
1411
|
// 确保value是数字
|
|
@@ -1385,7 +1416,7 @@ MongoDB.prototype.decrby = async function (key, value = 1, seconds = 0) {
|
|
|
1385
1416
|
const returnResult = result !== undefined ? result : 0;
|
|
1386
1417
|
|
|
1387
1418
|
// 触发后置事件
|
|
1388
|
-
this.emit('
|
|
1419
|
+
this.emit('decrby:after', {
|
|
1389
1420
|
key: finalKey,
|
|
1390
1421
|
value: finalValue,
|
|
1391
1422
|
seconds: finalSeconds,
|
|
@@ -1396,13 +1427,13 @@ MongoDB.prototype.decrby = async function (key, value = 1, seconds = 0) {
|
|
|
1396
1427
|
return returnResult;
|
|
1397
1428
|
} catch (error) {
|
|
1398
1429
|
// 触发错误事件
|
|
1399
|
-
this.emit('
|
|
1430
|
+
this.emit('decrby:error', {
|
|
1400
1431
|
key,
|
|
1401
1432
|
value,
|
|
1402
1433
|
seconds,
|
|
1403
1434
|
error
|
|
1404
1435
|
});
|
|
1405
|
-
|
|
1436
|
+
this.logger('error', '递减操作失败:', error);
|
|
1406
1437
|
return 0;
|
|
1407
1438
|
}
|
|
1408
1439
|
};
|
|
@@ -1422,11 +1453,11 @@ MongoDB.prototype.incrbyfloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
1422
1453
|
seconds,
|
|
1423
1454
|
cancel: false
|
|
1424
1455
|
};
|
|
1425
|
-
this.emit('
|
|
1456
|
+
this.emit('incrbyfloat:before', beforeEventData);
|
|
1426
1457
|
|
|
1427
1458
|
// 如果事件处理器标记为取消,则返回默认值
|
|
1428
1459
|
if (beforeEventData.cancel) {
|
|
1429
|
-
|
|
1460
|
+
this.logger('debug', 'incrbyfloat操作被事件处理器取消');
|
|
1430
1461
|
return 0.0;
|
|
1431
1462
|
}
|
|
1432
1463
|
|
|
@@ -1438,9 +1469,8 @@ MongoDB.prototype.incrbyfloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
1438
1469
|
} = beforeEventData;
|
|
1439
1470
|
|
|
1440
1471
|
// 参数验证
|
|
1441
|
-
if (
|
|
1442
|
-
|
|
1443
|
-
return 0.0;
|
|
1472
|
+
if (typeof finalKey !== 'string' || !finalKey) {
|
|
1473
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1444
1474
|
}
|
|
1445
1475
|
|
|
1446
1476
|
// 确保value是数字
|
|
@@ -1451,7 +1481,7 @@ MongoDB.prototype.incrbyfloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
1451
1481
|
const returnResult = result !== undefined ? result : 0.0;
|
|
1452
1482
|
|
|
1453
1483
|
// 触发后置事件
|
|
1454
|
-
this.emit('
|
|
1484
|
+
this.emit('incrbyfloat:after', {
|
|
1455
1485
|
key: finalKey,
|
|
1456
1486
|
value: finalValue,
|
|
1457
1487
|
seconds: finalSeconds,
|
|
@@ -1462,13 +1492,13 @@ MongoDB.prototype.incrbyfloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
1462
1492
|
return returnResult;
|
|
1463
1493
|
} catch (error) {
|
|
1464
1494
|
// 触发错误事件
|
|
1465
|
-
this.emit('
|
|
1495
|
+
this.emit('incrbyfloat:error', {
|
|
1466
1496
|
key,
|
|
1467
1497
|
value,
|
|
1468
1498
|
seconds,
|
|
1469
1499
|
error
|
|
1470
1500
|
});
|
|
1471
|
-
|
|
1501
|
+
this.logger('error', '浮点递增操作失败:', error);
|
|
1472
1502
|
return 0.0;
|
|
1473
1503
|
}
|
|
1474
1504
|
};
|
|
@@ -1476,43 +1506,46 @@ MongoDB.prototype.incrbyfloat = async function (key, value = 1.0, seconds = 0) {
|
|
|
1476
1506
|
/**
|
|
1477
1507
|
* @description Redis兼容API - 检查键是否存在
|
|
1478
1508
|
* @param {String|Array<String>} key 键名或键名数组
|
|
1479
|
-
* @return {Promise<
|
|
1509
|
+
* @return {Promise<boolean>} 是否存在
|
|
1480
1510
|
*/
|
|
1481
1511
|
MongoDB.prototype.exists = async function (key) {
|
|
1482
1512
|
try {
|
|
1483
1513
|
await this._ensureConnected();
|
|
1484
1514
|
|
|
1515
|
+
// 参数验证
|
|
1516
|
+
if (!key) {
|
|
1517
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1485
1520
|
// 验证数组中的每个元素都是非空字符串
|
|
1486
1521
|
if (Array.isArray(key)) {
|
|
1487
1522
|
for (const k of key) {
|
|
1488
1523
|
if (typeof k !== 'string' || !k) {
|
|
1489
|
-
throw new
|
|
1524
|
+
throw new TypeError('key数组中的每个元素必须是非空字符串');
|
|
1490
1525
|
}
|
|
1491
1526
|
}
|
|
1527
|
+
} else if (typeof key !== 'string') {
|
|
1528
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
1492
1529
|
}
|
|
1493
1530
|
|
|
1494
|
-
let existsCount = 0;
|
|
1495
|
-
|
|
1496
1531
|
// 检查输入类型并处理
|
|
1497
1532
|
if (Array.isArray(key)) {
|
|
1498
|
-
//
|
|
1533
|
+
// 处理多键检查:只要有一个键存在就返回true
|
|
1499
1534
|
const results = await this.find({
|
|
1500
1535
|
key: {
|
|
1501
1536
|
$in: key
|
|
1502
1537
|
}
|
|
1503
1538
|
});
|
|
1504
|
-
|
|
1539
|
+
return results.length > 0;
|
|
1505
1540
|
} else {
|
|
1506
1541
|
// 处理单键检查
|
|
1507
1542
|
const result = await this.findOne({
|
|
1508
1543
|
key: key
|
|
1509
1544
|
});
|
|
1510
|
-
|
|
1545
|
+
return result !== null;
|
|
1511
1546
|
}
|
|
1512
|
-
|
|
1513
|
-
return existsCount;
|
|
1514
1547
|
} catch (error) {
|
|
1515
|
-
|
|
1548
|
+
this.logger('error', '检查键是否存在失败:', error);
|
|
1516
1549
|
throw error;
|
|
1517
1550
|
}
|
|
1518
1551
|
};
|
|
@@ -1542,9 +1575,9 @@ MongoDB.prototype._set = async function (key, value, expire) {
|
|
|
1542
1575
|
);
|
|
1543
1576
|
return true;
|
|
1544
1577
|
} catch (error) {
|
|
1545
|
-
|
|
1546
|
-
return false;
|
|
1547
|
-
}
|
|
1578
|
+
this.logger('error', '设置缓存失败:', error);
|
|
1579
|
+
return false;
|
|
1580
|
+
} // 与CacheBase保持一致,返回false而不是抛出异常
|
|
1548
1581
|
};
|
|
1549
1582
|
|
|
1550
1583
|
/**
|
|
@@ -1562,13 +1595,13 @@ MongoDB.prototype.set = async function (key, value, seconds = 0) {
|
|
|
1562
1595
|
* @description Redis兼容API - 哈希表批量设置
|
|
1563
1596
|
* @param {String} key 键名
|
|
1564
1597
|
* @param {Array} fieldValues 字段值对数组,格式: [field1, value1, field2, value2, ...] 或对象格式 {field1: value1, field2: value2}
|
|
1565
|
-
* @return {Promise<
|
|
1598
|
+
* @return {Promise<Boolean>} 操作结果
|
|
1566
1599
|
*/
|
|
1567
1600
|
MongoDB.prototype.hmset = async function (key, ...fieldValues) {
|
|
1568
1601
|
try {
|
|
1569
1602
|
// 参数验证
|
|
1570
1603
|
if (!key || typeof key !== 'string') {
|
|
1571
|
-
|
|
1604
|
+
this.logger('warn', 'hmset: 键名无效');
|
|
1572
1605
|
return 0;
|
|
1573
1606
|
}
|
|
1574
1607
|
|
|
@@ -1587,8 +1620,6 @@ MongoDB.prototype.hmset = async function (key, ...fieldValues) {
|
|
|
1587
1620
|
}
|
|
1588
1621
|
}
|
|
1589
1622
|
|
|
1590
|
-
const fieldsCount = Object.keys(hashData).length;
|
|
1591
|
-
|
|
1592
1623
|
// 确保连接
|
|
1593
1624
|
await this._ensureConnected();
|
|
1594
1625
|
|
|
@@ -1617,10 +1648,10 @@ MongoDB.prototype.hmset = async function (key, ...fieldValues) {
|
|
|
1617
1648
|
await this.addObj(data);
|
|
1618
1649
|
}
|
|
1619
1650
|
|
|
1620
|
-
return
|
|
1651
|
+
return true; // 操作成功返回true
|
|
1621
1652
|
} catch (error) {
|
|
1622
|
-
|
|
1623
|
-
return
|
|
1653
|
+
this.logger('error', '[hmset] 哈希表批量设置失败:', error);
|
|
1654
|
+
return false; // 操作失败返回false
|
|
1624
1655
|
}
|
|
1625
1656
|
};
|
|
1626
1657
|
|
|
@@ -1656,7 +1687,7 @@ MongoDB.prototype.hmget = async function (key, fields) {
|
|
|
1656
1687
|
|
|
1657
1688
|
return values;
|
|
1658
1689
|
} catch (error) {
|
|
1659
|
-
|
|
1690
|
+
this.logger('error', 'hmget操作失败:', error);
|
|
1660
1691
|
// 错误时返回与fields长度相同的null数组
|
|
1661
1692
|
const fieldArray = Array.isArray(fields) ? fields : [fields];
|
|
1662
1693
|
return fieldArray.map(() => null);
|
|
@@ -1670,6 +1701,14 @@ MongoDB.prototype.hmget = async function (key, fields) {
|
|
|
1670
1701
|
* @return {Promise<Boolean>} 是否成功
|
|
1671
1702
|
*/
|
|
1672
1703
|
MongoDB.prototype.hdelMulti = async function (key, fields) {
|
|
1704
|
+
// 参数校验
|
|
1705
|
+
if (typeof key !== 'string' || !key) {
|
|
1706
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1707
|
+
}
|
|
1708
|
+
if (!Array.isArray(fields) || fields.length === 0) {
|
|
1709
|
+
throw new TypeError('fields必须是非空数组');
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1673
1712
|
try {
|
|
1674
1713
|
await this._ensureConnected();
|
|
1675
1714
|
const item = await this.findOne({
|
|
@@ -1696,7 +1735,7 @@ MongoDB.prototype.hdelMulti = async function (key, fields) {
|
|
|
1696
1735
|
}
|
|
1697
1736
|
return deleted;
|
|
1698
1737
|
} catch (error) {
|
|
1699
|
-
|
|
1738
|
+
this.logger('error', '增加整数值失败:', error);
|
|
1700
1739
|
return false;
|
|
1701
1740
|
}
|
|
1702
1741
|
};
|
|
@@ -1707,6 +1746,11 @@ MongoDB.prototype.hdelMulti = async function (key, fields) {
|
|
|
1707
1746
|
* @return {Promise<Array>} 值数组
|
|
1708
1747
|
*/
|
|
1709
1748
|
MongoDB.prototype.hvals = async function (key) {
|
|
1749
|
+
// 参数校验
|
|
1750
|
+
if (typeof key !== 'string' || !key) {
|
|
1751
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1710
1754
|
try {
|
|
1711
1755
|
await this._ensureConnected();
|
|
1712
1756
|
const item = await this.findOne({
|
|
@@ -1717,7 +1761,7 @@ MongoDB.prototype.hvals = async function (key) {
|
|
|
1717
1761
|
}
|
|
1718
1762
|
return Object.values(item.value);
|
|
1719
1763
|
} catch (error) {
|
|
1720
|
-
|
|
1764
|
+
this.logger('error', '哈希表获取所有值失败:', error);
|
|
1721
1765
|
return [];
|
|
1722
1766
|
}
|
|
1723
1767
|
};
|
|
@@ -1728,6 +1772,11 @@ MongoDB.prototype.hvals = async function (key) {
|
|
|
1728
1772
|
* @return {Promise<Array>} 字段名数组
|
|
1729
1773
|
*/
|
|
1730
1774
|
MongoDB.prototype.hkeys = async function (key) {
|
|
1775
|
+
// 参数校验
|
|
1776
|
+
if (typeof key !== 'string' || !key) {
|
|
1777
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1731
1780
|
try {
|
|
1732
1781
|
await this._ensureConnected();
|
|
1733
1782
|
const item = await this.findOne({
|
|
@@ -1738,7 +1787,7 @@ MongoDB.prototype.hkeys = async function (key) {
|
|
|
1738
1787
|
}
|
|
1739
1788
|
return Object.keys(item.value);
|
|
1740
1789
|
} catch (error) {
|
|
1741
|
-
|
|
1790
|
+
this.logger('error', '哈希表获取所有字段名失败:', error);
|
|
1742
1791
|
return [];
|
|
1743
1792
|
}
|
|
1744
1793
|
};
|
|
@@ -1749,12 +1798,12 @@ MongoDB.prototype.hkeys = async function (key) {
|
|
|
1749
1798
|
* @return {Promise<Number>} 字段数量
|
|
1750
1799
|
*/
|
|
1751
1800
|
MongoDB.prototype.hlen = async function (key) {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
}
|
|
1801
|
+
// 参数校验
|
|
1802
|
+
if (typeof key !== 'string' || !key) {
|
|
1803
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1804
|
+
}
|
|
1757
1805
|
|
|
1806
|
+
try {
|
|
1758
1807
|
await this._ensureConnected();
|
|
1759
1808
|
const item = await this.findOne({ key: key });
|
|
1760
1809
|
|
|
@@ -1766,7 +1815,7 @@ MongoDB.prototype.hlen = async function (key) {
|
|
|
1766
1815
|
// 使用Object.keys获取自有属性数量,这比for-in循环更高效
|
|
1767
1816
|
return Object.keys(item.value).length;
|
|
1768
1817
|
} catch (error) {
|
|
1769
|
-
|
|
1818
|
+
this.logger('error', 'hlen操作失败:', error);
|
|
1770
1819
|
return 0;
|
|
1771
1820
|
}
|
|
1772
1821
|
};
|
|
@@ -1778,6 +1827,14 @@ MongoDB.prototype.hlen = async function (key) {
|
|
|
1778
1827
|
* @return {Promise<Boolean>} 是否存在
|
|
1779
1828
|
*/
|
|
1780
1829
|
MongoDB.prototype.hexists = async function (key, field) {
|
|
1830
|
+
// 参数校验
|
|
1831
|
+
if (typeof key !== 'string' || !key) {
|
|
1832
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1833
|
+
}
|
|
1834
|
+
if (typeof field !== 'string' || !field) {
|
|
1835
|
+
throw new TypeError('field必须是有效的字符串');
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1781
1838
|
try {
|
|
1782
1839
|
await this._ensureConnected();
|
|
1783
1840
|
const item = await this.findOne({
|
|
@@ -1788,7 +1845,7 @@ MongoDB.prototype.hexists = async function (key, field) {
|
|
|
1788
1845
|
}
|
|
1789
1846
|
return field in item.value;
|
|
1790
1847
|
} catch (error) {
|
|
1791
|
-
|
|
1848
|
+
this.logger('error', '哈希表字段是否存在失败:', error);
|
|
1792
1849
|
return false;
|
|
1793
1850
|
}
|
|
1794
1851
|
};
|
|
@@ -1800,6 +1857,11 @@ MongoDB.prototype.hexists = async function (key, field) {
|
|
|
1800
1857
|
* @return {Promise<Number>} 添加后列表长度
|
|
1801
1858
|
*/
|
|
1802
1859
|
MongoDB.prototype.rpush = async function (key, value) {
|
|
1860
|
+
// 参数校验
|
|
1861
|
+
if (typeof key !== 'string' || !key) {
|
|
1862
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1803
1865
|
try {
|
|
1804
1866
|
await this._ensureConnected();
|
|
1805
1867
|
const item = await this.findOne({
|
|
@@ -1812,7 +1874,7 @@ MongoDB.prototype.rpush = async function (key, value) {
|
|
|
1812
1874
|
await this._add(key, list);
|
|
1813
1875
|
return list.length;
|
|
1814
1876
|
} catch (error) {
|
|
1815
|
-
|
|
1877
|
+
this.logger('error', '列表尾部添加失败:', error);
|
|
1816
1878
|
return 0;
|
|
1817
1879
|
}
|
|
1818
1880
|
};
|
|
@@ -1824,6 +1886,11 @@ MongoDB.prototype.rpush = async function (key, value) {
|
|
|
1824
1886
|
* @return {Promise<Number>} 添加后列表长度
|
|
1825
1887
|
*/
|
|
1826
1888
|
MongoDB.prototype.lpush = async function (key, value) {
|
|
1889
|
+
// 参数校验
|
|
1890
|
+
if (typeof key !== 'string' || !key) {
|
|
1891
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1827
1894
|
try {
|
|
1828
1895
|
await this._ensureConnected();
|
|
1829
1896
|
const item = await this.findOne({
|
|
@@ -1836,7 +1903,7 @@ MongoDB.prototype.lpush = async function (key, value) {
|
|
|
1836
1903
|
await this._add(key, list);
|
|
1837
1904
|
return list.length;
|
|
1838
1905
|
} catch (error) {
|
|
1839
|
-
|
|
1906
|
+
this.logger('error', '列表头部添加失败:', error);
|
|
1840
1907
|
return 0;
|
|
1841
1908
|
}
|
|
1842
1909
|
};
|
|
@@ -1849,6 +1916,17 @@ MongoDB.prototype.lpush = async function (key, value) {
|
|
|
1849
1916
|
* @return {Promise<Array>} 元素数组
|
|
1850
1917
|
*/
|
|
1851
1918
|
MongoDB.prototype.lrange = async function (key, start, stop) {
|
|
1919
|
+
// 参数校验
|
|
1920
|
+
if (typeof key !== 'string' || !key) {
|
|
1921
|
+
throw new TypeError('key必须是有效的字符串');
|
|
1922
|
+
}
|
|
1923
|
+
if (typeof start !== 'number' || isNaN(start)) {
|
|
1924
|
+
throw new TypeError('start必须是有效的数字');
|
|
1925
|
+
}
|
|
1926
|
+
if (typeof stop !== 'number' || isNaN(stop)) {
|
|
1927
|
+
throw new TypeError('stop必须是有效的数字');
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1852
1930
|
try {
|
|
1853
1931
|
await this._ensureConnected();
|
|
1854
1932
|
const item = await this.findOne({
|
|
@@ -1868,7 +1946,7 @@ MongoDB.prototype.lrange = async function (key, start, stop) {
|
|
|
1868
1946
|
|
|
1869
1947
|
return item.value.slice(startIndex, endIndex + 1);
|
|
1870
1948
|
} catch (error) {
|
|
1871
|
-
|
|
1949
|
+
this.logger('error', '列表范围查询失败:', error);
|
|
1872
1950
|
return [];
|
|
1873
1951
|
}
|
|
1874
1952
|
};
|
|
@@ -1898,7 +1976,7 @@ MongoDB.prototype.lindex = async function (key, index) {
|
|
|
1898
1976
|
|
|
1899
1977
|
return item.value[realIndex];
|
|
1900
1978
|
} catch (error) {
|
|
1901
|
-
|
|
1979
|
+
this.logger('error', '获取列表索引元素失败:', error);
|
|
1902
1980
|
return null;
|
|
1903
1981
|
}
|
|
1904
1982
|
};
|
|
@@ -1935,7 +2013,7 @@ MongoDB.prototype.lset = async function (key, index, value) {
|
|
|
1935
2013
|
});
|
|
1936
2014
|
return true;
|
|
1937
2015
|
} catch (error) {
|
|
1938
|
-
|
|
2016
|
+
this.logger('error', '设置列表索引元素失败:', error);
|
|
1939
2017
|
return false;
|
|
1940
2018
|
}
|
|
1941
2019
|
};
|
|
@@ -1994,7 +2072,7 @@ MongoDB.prototype.lrem = async function (key, count, value) {
|
|
|
1994
2072
|
|
|
1995
2073
|
return removedCount;
|
|
1996
2074
|
} catch (error) {
|
|
1997
|
-
|
|
2075
|
+
this.logger('error', '删除列表元素失败:', error);
|
|
1998
2076
|
return 0;
|
|
1999
2077
|
}
|
|
2000
2078
|
};
|
|
@@ -2025,7 +2103,7 @@ MongoDB.prototype.ltrim = async function (key, start, stop) {
|
|
|
2025
2103
|
});
|
|
2026
2104
|
return true;
|
|
2027
2105
|
} catch (error) {
|
|
2028
|
-
|
|
2106
|
+
this.logger('error', '增加整数值失败:', error);
|
|
2029
2107
|
return false;
|
|
2030
2108
|
}
|
|
2031
2109
|
};
|
|
@@ -2036,6 +2114,11 @@ MongoDB.prototype.ltrim = async function (key, start, stop) {
|
|
|
2036
2114
|
* @return {Promise<Number>} 列表长度
|
|
2037
2115
|
*/
|
|
2038
2116
|
MongoDB.prototype.llen = async function (key) {
|
|
2117
|
+
// 参数校验
|
|
2118
|
+
if (typeof key !== 'string' || !key) {
|
|
2119
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2039
2122
|
try {
|
|
2040
2123
|
await this._ensureConnected();
|
|
2041
2124
|
const item = await this.findOne({
|
|
@@ -2046,7 +2129,7 @@ MongoDB.prototype.llen = async function (key) {
|
|
|
2046
2129
|
}
|
|
2047
2130
|
return item.value.length;
|
|
2048
2131
|
} catch (error) {
|
|
2049
|
-
|
|
2132
|
+
this.logger('error', '获取列表长度失败:', error);
|
|
2050
2133
|
return 0;
|
|
2051
2134
|
}
|
|
2052
2135
|
};
|
|
@@ -2058,6 +2141,14 @@ MongoDB.prototype.llen = async function (key) {
|
|
|
2058
2141
|
* @return {Promise<Number>} 添加的成员数量
|
|
2059
2142
|
*/
|
|
2060
2143
|
MongoDB.prototype.saddMulti = async function (key, members) {
|
|
2144
|
+
// 参数校验
|
|
2145
|
+
if (typeof key !== 'string' || !key) {
|
|
2146
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2147
|
+
}
|
|
2148
|
+
if (!Array.isArray(members)) {
|
|
2149
|
+
throw new TypeError('members必须是有效的数组');
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2061
2152
|
try {
|
|
2062
2153
|
await this._ensureConnected();
|
|
2063
2154
|
const item = await this.findOne({
|
|
@@ -2079,7 +2170,7 @@ MongoDB.prototype.saddMulti = async function (key, members) {
|
|
|
2079
2170
|
|
|
2080
2171
|
return addedCount;
|
|
2081
2172
|
} catch (error) {
|
|
2082
|
-
|
|
2173
|
+
this.logger('error', '集合并发添加失败:', error);
|
|
2083
2174
|
return 0;
|
|
2084
2175
|
}
|
|
2085
2176
|
};
|
|
@@ -2091,6 +2182,14 @@ MongoDB.prototype.saddMulti = async function (key, members) {
|
|
|
2091
2182
|
* @return {Promise<Number>} 删除的成员数量
|
|
2092
2183
|
*/
|
|
2093
2184
|
MongoDB.prototype.sremMulti = async function (key, members) {
|
|
2185
|
+
// 参数校验
|
|
2186
|
+
if (typeof key !== 'string' || !key) {
|
|
2187
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2188
|
+
}
|
|
2189
|
+
if (!Array.isArray(members)) {
|
|
2190
|
+
throw new TypeError('members必须是有效的数组');
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2094
2193
|
try {
|
|
2095
2194
|
await this._ensureConnected();
|
|
2096
2195
|
const item = await this.findOne({
|
|
@@ -2114,101 +2213,145 @@ MongoDB.prototype.sremMulti = async function (key, members) {
|
|
|
2114
2213
|
|
|
2115
2214
|
return removedCount;
|
|
2116
2215
|
} catch (error) {
|
|
2117
|
-
|
|
2216
|
+
this.logger('error', '集合并发删除失败:', error);
|
|
2118
2217
|
return 0;
|
|
2119
2218
|
}
|
|
2120
2219
|
};
|
|
2121
2220
|
|
|
2122
2221
|
/**
|
|
2123
2222
|
* @description Redis兼容API - 集合差集
|
|
2124
|
-
* @param {String}
|
|
2125
|
-
* @param {String} key2 第二个集合键
|
|
2223
|
+
* @param {...String} keys 集合键(至少两个)
|
|
2126
2224
|
* @return {Promise<Array>} 差集数组
|
|
2127
2225
|
*/
|
|
2128
|
-
MongoDB.prototype.sdiff = async function (
|
|
2226
|
+
MongoDB.prototype.sdiff = async function (...keys) {
|
|
2227
|
+
// 参数校验
|
|
2228
|
+
if (!Array.isArray(keys) || keys.length < 2) {
|
|
2229
|
+
throw new TypeError('必须提供至少两个集合键');
|
|
2230
|
+
}
|
|
2231
|
+
for (const key of keys) {
|
|
2232
|
+
if (typeof key !== 'string' || !key) {
|
|
2233
|
+
throw new TypeError('所有集合键必须是有效的字符串');
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2129
2237
|
try {
|
|
2130
2238
|
await this._ensureConnected();
|
|
2131
|
-
const item1 = await this.findOne({
|
|
2132
|
-
key: key1
|
|
2133
|
-
});
|
|
2134
|
-
const item2 = await this.findOne({
|
|
2135
|
-
key: key2
|
|
2136
|
-
});
|
|
2137
2239
|
|
|
2138
|
-
|
|
2139
|
-
const
|
|
2240
|
+
// 获取所有集合的数据
|
|
2241
|
+
const items = await Promise.all(keys.map(key => this.findOne({ key })));
|
|
2242
|
+
|
|
2243
|
+
// 转换为集合数组
|
|
2244
|
+
const sets = items.map(item =>
|
|
2245
|
+
item && Array.isArray(item.value) ? [...new Set(item.value)] : []
|
|
2246
|
+
);
|
|
2247
|
+
|
|
2248
|
+
// 第一个集合作为基准
|
|
2249
|
+
const baseSet = sets[0];
|
|
2140
2250
|
|
|
2141
|
-
//
|
|
2142
|
-
const
|
|
2251
|
+
// 创建其他所有集合的字符串表示的并集用于快速查找
|
|
2252
|
+
const otherSetsStr = new Set();
|
|
2253
|
+
for (let i = 1; i < sets.length; i++) {
|
|
2254
|
+
sets[i].forEach(member => {
|
|
2255
|
+
otherSetsStr.add(JSON.stringify(member));
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2143
2258
|
|
|
2144
|
-
// 找出在
|
|
2145
|
-
return
|
|
2259
|
+
// 找出在baseSet中但不在其他所有集合中的元素
|
|
2260
|
+
return baseSet.filter(member => !otherSetsStr.has(JSON.stringify(member)));
|
|
2146
2261
|
} catch (error) {
|
|
2147
|
-
|
|
2262
|
+
this.logger('error', '集合差集失败:', error);
|
|
2148
2263
|
return [];
|
|
2149
2264
|
}
|
|
2150
2265
|
};
|
|
2151
2266
|
|
|
2152
2267
|
/**
|
|
2153
2268
|
* @description Redis兼容API - 集合交集
|
|
2154
|
-
* @param {String}
|
|
2155
|
-
* @param {String} key2 第二个集合键
|
|
2269
|
+
* @param {...String} keys 集合键(至少两个)
|
|
2156
2270
|
* @return {Promise<Array>} 交集数组
|
|
2157
2271
|
*/
|
|
2158
|
-
MongoDB.prototype.sinter = async function (
|
|
2272
|
+
MongoDB.prototype.sinter = async function (...keys) {
|
|
2273
|
+
// 参数校验
|
|
2274
|
+
if (!Array.isArray(keys) || keys.length < 2) {
|
|
2275
|
+
throw new TypeError('必须提供至少两个集合键');
|
|
2276
|
+
}
|
|
2277
|
+
for (const key of keys) {
|
|
2278
|
+
if (typeof key !== 'string' || !key) {
|
|
2279
|
+
throw new TypeError('所有集合键必须是有效的字符串');
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2159
2283
|
try {
|
|
2160
2284
|
await this._ensureConnected();
|
|
2161
|
-
const item1 = await this.findOne({
|
|
2162
|
-
key: key1
|
|
2163
|
-
});
|
|
2164
|
-
const item2 = await this.findOne({
|
|
2165
|
-
key: key2
|
|
2166
|
-
});
|
|
2167
2285
|
|
|
2168
|
-
|
|
2169
|
-
const
|
|
2286
|
+
// 获取所有集合的数据
|
|
2287
|
+
const items = await Promise.all(keys.map(key => this.findOne({ key })));
|
|
2170
2288
|
|
|
2171
|
-
//
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2289
|
+
// 转换为集合数组
|
|
2290
|
+
const sets = items.map(item =>
|
|
2291
|
+
item && Array.isArray(item.value) ? [...new Set(item.value)] : []
|
|
2292
|
+
);
|
|
2293
|
+
|
|
2294
|
+
// 如果有一个集合为空,交集就是空
|
|
2295
|
+
if (sets.some(set => set.length === 0)) {
|
|
2296
|
+
return [];
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
// 找到最小的集合作为基准
|
|
2300
|
+
let smallestSet = sets[0];
|
|
2301
|
+
let smallestIndex = 0;
|
|
2302
|
+
for (let i = 1; i < sets.length; i++) {
|
|
2303
|
+
if (sets[i].length < smallestSet.length) {
|
|
2304
|
+
smallestSet = sets[i];
|
|
2305
|
+
smallestIndex = i;
|
|
2306
|
+
}
|
|
2179
2307
|
}
|
|
2180
2308
|
|
|
2181
|
-
|
|
2309
|
+
// 创建其他集合的字符串表示用于快速查找
|
|
2310
|
+
const otherSetsStr = sets.map((set, index) =>
|
|
2311
|
+
index !== smallestIndex ? new Set(set.map(m => JSON.stringify(m))) : null
|
|
2312
|
+
).filter(Boolean);
|
|
2182
2313
|
|
|
2183
|
-
//
|
|
2184
|
-
return
|
|
2314
|
+
// 找出同时存在于所有集合中的元素
|
|
2315
|
+
return smallestSet.filter(member => {
|
|
2316
|
+
const memberStr = JSON.stringify(member);
|
|
2317
|
+
return otherSetsStr.every(set => set.has(memberStr));
|
|
2318
|
+
});
|
|
2185
2319
|
} catch (error) {
|
|
2186
|
-
|
|
2320
|
+
this.logger('error', '集合交集失败:', error);
|
|
2187
2321
|
return [];
|
|
2188
2322
|
}
|
|
2189
2323
|
};
|
|
2190
2324
|
|
|
2191
2325
|
/**
|
|
2192
2326
|
* @description Redis兼容API - 集合并集
|
|
2193
|
-
* @param {String}
|
|
2194
|
-
* @param {String} key2 第二个集合键
|
|
2327
|
+
* @param {...String} keys 集合键(至少两个)
|
|
2195
2328
|
* @return {Promise<Array>} 并集数组
|
|
2196
2329
|
*/
|
|
2197
|
-
MongoDB.prototype.sunion = async function (
|
|
2330
|
+
MongoDB.prototype.sunion = async function (...keys) {
|
|
2331
|
+
// 参数校验
|
|
2332
|
+
if (!Array.isArray(keys) || keys.length < 2) {
|
|
2333
|
+
throw new TypeError('必须提供至少两个集合键');
|
|
2334
|
+
}
|
|
2335
|
+
for (const key of keys) {
|
|
2336
|
+
if (typeof key !== 'string' || !key) {
|
|
2337
|
+
throw new TypeError('所有集合键必须是有效的字符串');
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2198
2341
|
try {
|
|
2199
2342
|
await this._ensureConnected();
|
|
2200
|
-
const item1 = await this.findOne({
|
|
2201
|
-
key: key1
|
|
2202
|
-
});
|
|
2203
|
-
const item2 = await this.findOne({
|
|
2204
|
-
key: key2
|
|
2205
|
-
});
|
|
2206
2343
|
|
|
2207
|
-
|
|
2208
|
-
const
|
|
2344
|
+
// 获取所有集合的数据
|
|
2345
|
+
const items = await Promise.all(keys.map(key => this.findOne({ key })));
|
|
2346
|
+
|
|
2347
|
+
// 转换为集合数组
|
|
2348
|
+
const sets = items.map(item =>
|
|
2349
|
+
item && Array.isArray(item.value) ? item.value : []
|
|
2350
|
+
);
|
|
2351
|
+
|
|
2352
|
+
// 合并所有集合
|
|
2353
|
+
const combined = sets.reduce((acc, set) => [...acc, ...set], []);
|
|
2209
2354
|
|
|
2210
|
-
// 合并并去重
|
|
2211
|
-
const combined = [...set1, ...set2];
|
|
2212
2355
|
// 使用Map进行对象去重,基于JSON字符串表示
|
|
2213
2356
|
const uniqueMap = new Map();
|
|
2214
2357
|
|
|
@@ -2221,7 +2364,7 @@ MongoDB.prototype.sunion = async function (key1, key2) {
|
|
|
2221
2364
|
|
|
2222
2365
|
return Array.from(uniqueMap.values());
|
|
2223
2366
|
} catch (error) {
|
|
2224
|
-
|
|
2367
|
+
this.logger('error', '集合并集失败:', error);
|
|
2225
2368
|
return [];
|
|
2226
2369
|
}
|
|
2227
2370
|
};
|
|
@@ -2232,6 +2375,11 @@ MongoDB.prototype.sunion = async function (key1, key2) {
|
|
|
2232
2375
|
* @return {Promise<Number>} 成员数量
|
|
2233
2376
|
*/
|
|
2234
2377
|
MongoDB.prototype.scard = async function (key) {
|
|
2378
|
+
// 参数校验
|
|
2379
|
+
if (typeof key !== 'string' || !key) {
|
|
2380
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2235
2383
|
try {
|
|
2236
2384
|
await this._ensureConnected();
|
|
2237
2385
|
const item = await this.findOne({
|
|
@@ -2245,7 +2393,7 @@ MongoDB.prototype.scard = async function (key) {
|
|
|
2245
2393
|
const uniqueItems = new Set(item.value.map(m => JSON.stringify(m)));
|
|
2246
2394
|
return uniqueItems.size;
|
|
2247
2395
|
} catch (error) {
|
|
2248
|
-
|
|
2396
|
+
this.logger('error', '获取集合成员数量失败:', error);
|
|
2249
2397
|
return 0;
|
|
2250
2398
|
}
|
|
2251
2399
|
};
|
|
@@ -2257,8 +2405,16 @@ MongoDB.prototype.scard = async function (key) {
|
|
|
2257
2405
|
* @return {Promise<Boolean>} 是否是成员
|
|
2258
2406
|
*/
|
|
2259
2407
|
MongoDB.prototype.sismember = async function (key, member) {
|
|
2408
|
+
// 参数校验
|
|
2409
|
+
if (typeof key !== 'string' || !key) {
|
|
2410
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2411
|
+
}
|
|
2412
|
+
if (member === undefined || member === null) {
|
|
2413
|
+
throw new TypeError('member不能为undefined或null');
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2260
2416
|
try {
|
|
2261
|
-
this.emit('
|
|
2417
|
+
this.emit('sismember:before', {
|
|
2262
2418
|
key,
|
|
2263
2419
|
member
|
|
2264
2420
|
});
|
|
@@ -2276,19 +2432,19 @@ MongoDB.prototype.sismember = async function (key, member) {
|
|
|
2276
2432
|
result = item.value.includes(memberStr);
|
|
2277
2433
|
}
|
|
2278
2434
|
|
|
2279
|
-
this.emit('
|
|
2435
|
+
this.emit('sismember:after', {
|
|
2280
2436
|
key,
|
|
2281
2437
|
member,
|
|
2282
2438
|
result
|
|
2283
2439
|
});
|
|
2284
2440
|
return result;
|
|
2285
2441
|
} catch (error) {
|
|
2286
|
-
this.emit('
|
|
2442
|
+
this.emit('sismember:error', {
|
|
2287
2443
|
key,
|
|
2288
2444
|
member,
|
|
2289
2445
|
error
|
|
2290
2446
|
});
|
|
2291
|
-
|
|
2447
|
+
this.logger('error', '检查集合成员失败:', error);
|
|
2292
2448
|
return false;
|
|
2293
2449
|
}
|
|
2294
2450
|
};
|
|
@@ -2299,7 +2455,7 @@ MongoDB.prototype.sismember = async function (key, member) {
|
|
|
2299
2455
|
*/
|
|
2300
2456
|
MongoDB.prototype.clearExpire = async function () {
|
|
2301
2457
|
try {
|
|
2302
|
-
this.emit('
|
|
2458
|
+
this.emit('clearExpire:before', {});
|
|
2303
2459
|
await this._ensureConnected();
|
|
2304
2460
|
// 删除所有已过期的数据
|
|
2305
2461
|
const result = await this.delete({
|
|
@@ -2308,15 +2464,15 @@ MongoDB.prototype.clearExpire = async function () {
|
|
|
2308
2464
|
$lt: new Date()
|
|
2309
2465
|
}
|
|
2310
2466
|
});
|
|
2311
|
-
this.emit('
|
|
2467
|
+
this.emit('clearExpire:after', {
|
|
2312
2468
|
result: true
|
|
2313
2469
|
});
|
|
2314
2470
|
return true;
|
|
2315
2471
|
} catch (error) {
|
|
2316
|
-
this.emit('
|
|
2472
|
+
this.emit('clearExpire:error', {
|
|
2317
2473
|
error
|
|
2318
2474
|
});
|
|
2319
|
-
|
|
2475
|
+
this.logger('error', '清空过期数据失败:', error);
|
|
2320
2476
|
return false;
|
|
2321
2477
|
}
|
|
2322
2478
|
};
|
|
@@ -2342,7 +2498,7 @@ MongoDB.prototype.mget = async function (...keys) {
|
|
|
2342
2498
|
// 返回与输入键顺序对应的数组,不存在的键对应位置返回undefined
|
|
2343
2499
|
return keyArray.map(key => resultMap.hasOwnProperty(key) ? resultMap[key] : undefined);
|
|
2344
2500
|
} catch (error) {
|
|
2345
|
-
|
|
2501
|
+
this.logger('error', '批量获取失败:', error);
|
|
2346
2502
|
throw error;
|
|
2347
2503
|
}
|
|
2348
2504
|
};
|
|
@@ -2360,11 +2516,11 @@ MongoDB.prototype.mset = async function (keyValues, seconds = 0) {
|
|
|
2360
2516
|
seconds,
|
|
2361
2517
|
cancel: false
|
|
2362
2518
|
};
|
|
2363
|
-
this.emit('
|
|
2519
|
+
this.emit('mset:before', beforeEventData);
|
|
2364
2520
|
|
|
2365
2521
|
// 如果事件处理器标记为取消,则返回false
|
|
2366
2522
|
if (beforeEventData.cancel) {
|
|
2367
|
-
|
|
2523
|
+
this.logger('debug', 'mset操作被事件处理器取消');
|
|
2368
2524
|
return false;
|
|
2369
2525
|
}
|
|
2370
2526
|
|
|
@@ -2376,7 +2532,7 @@ MongoDB.prototype.mset = async function (keyValues, seconds = 0) {
|
|
|
2376
2532
|
|
|
2377
2533
|
// 参数验证,确保keyValues是对象且不为null
|
|
2378
2534
|
if (typeof finalData !== 'object' || finalData === null || Array.isArray(finalData)) {
|
|
2379
|
-
|
|
2535
|
+
this.logger('warn', 'mset: 参数必须是非空对象');
|
|
2380
2536
|
return false;
|
|
2381
2537
|
}
|
|
2382
2538
|
|
|
@@ -2386,7 +2542,7 @@ MongoDB.prototype.mset = async function (keyValues, seconds = 0) {
|
|
|
2386
2542
|
}
|
|
2387
2543
|
|
|
2388
2544
|
// 触发后置事件
|
|
2389
|
-
this.emit('
|
|
2545
|
+
this.emit('mset:after', {
|
|
2390
2546
|
keyValues: finalData,
|
|
2391
2547
|
seconds: finalSeconds,
|
|
2392
2548
|
result: true
|
|
@@ -2394,12 +2550,12 @@ MongoDB.prototype.mset = async function (keyValues, seconds = 0) {
|
|
|
2394
2550
|
return true;
|
|
2395
2551
|
} catch (error) {
|
|
2396
2552
|
// 触发错误事件
|
|
2397
|
-
this.emit('
|
|
2553
|
+
this.emit('mset:error', {
|
|
2398
2554
|
keyValues,
|
|
2399
2555
|
seconds,
|
|
2400
2556
|
error
|
|
2401
2557
|
});
|
|
2402
|
-
|
|
2558
|
+
this.logger('error', '批量设置失败:', error);
|
|
2403
2559
|
return false;
|
|
2404
2560
|
}
|
|
2405
2561
|
};
|
|
@@ -2412,6 +2568,14 @@ MongoDB.prototype.mset = async function (keyValues, seconds = 0) {
|
|
|
2412
2568
|
* @return {Promise<Boolean>} 是否成功
|
|
2413
2569
|
*/
|
|
2414
2570
|
MongoDB.prototype.zadd = async function (key, score, member) {
|
|
2571
|
+
// 参数校验
|
|
2572
|
+
if (typeof key !== 'string' || !key) {
|
|
2573
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2574
|
+
}
|
|
2575
|
+
if (typeof score !== 'number' || isNaN(score)) {
|
|
2576
|
+
throw new TypeError('score必须是有效的数字');
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2415
2579
|
try {
|
|
2416
2580
|
await this._ensureConnected();
|
|
2417
2581
|
const item = await this.findOne({
|
|
@@ -2437,7 +2601,7 @@ MongoDB.prototype.zadd = async function (key, score, member) {
|
|
|
2437
2601
|
await this._add(key, sortedSet);
|
|
2438
2602
|
return true;
|
|
2439
2603
|
} catch (error) {
|
|
2440
|
-
|
|
2604
|
+
this.logger('error', '增加浮点数值失败:', error);
|
|
2441
2605
|
return false;
|
|
2442
2606
|
}
|
|
2443
2607
|
};
|
|
@@ -2450,6 +2614,17 @@ MongoDB.prototype.zadd = async function (key, score, member) {
|
|
|
2450
2614
|
* @return {Promise<Array>} 成员数组
|
|
2451
2615
|
*/
|
|
2452
2616
|
MongoDB.prototype.zrangebyscore = async function (key, min, max) {
|
|
2617
|
+
// 参数校验
|
|
2618
|
+
if (typeof key !== 'string' || !key) {
|
|
2619
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2620
|
+
}
|
|
2621
|
+
if (typeof min !== 'number' || isNaN(min)) {
|
|
2622
|
+
throw new TypeError('min必须是有效的数字');
|
|
2623
|
+
}
|
|
2624
|
+
if (typeof max !== 'number' || isNaN(max)) {
|
|
2625
|
+
throw new TypeError('max必须是有效的数字');
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2453
2628
|
try {
|
|
2454
2629
|
await this._ensureConnected();
|
|
2455
2630
|
const item = await this.findOne({
|
|
@@ -2464,7 +2639,7 @@ MongoDB.prototype.zrangebyscore = async function (key, min, max) {
|
|
|
2464
2639
|
.filter(item => item.score >= min && item.score <= max)
|
|
2465
2640
|
.map(item => item.member);
|
|
2466
2641
|
} catch (error) {
|
|
2467
|
-
|
|
2642
|
+
this.logger('error', '有序集合范围查询失败:', error);
|
|
2468
2643
|
return [];
|
|
2469
2644
|
}
|
|
2470
2645
|
};
|
|
@@ -2475,6 +2650,11 @@ MongoDB.prototype.zrangebyscore = async function (key, min, max) {
|
|
|
2475
2650
|
* @return {Promise<Number>} 成员数量
|
|
2476
2651
|
*/
|
|
2477
2652
|
MongoDB.prototype.zcard = async function (key) {
|
|
2653
|
+
// 参数校验
|
|
2654
|
+
if (typeof key !== 'string' || !key) {
|
|
2655
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2478
2658
|
try {
|
|
2479
2659
|
await this._ensureConnected();
|
|
2480
2660
|
const item = await this.findOne({
|
|
@@ -2485,7 +2665,7 @@ MongoDB.prototype.zcard = async function (key) {
|
|
|
2485
2665
|
}
|
|
2486
2666
|
return item.value.length;
|
|
2487
2667
|
} catch (error) {
|
|
2488
|
-
|
|
2668
|
+
this.logger('error', '有序集合成员数量失败:', error);
|
|
2489
2669
|
return 0;
|
|
2490
2670
|
}
|
|
2491
2671
|
};
|
|
@@ -2497,6 +2677,11 @@ MongoDB.prototype.zcard = async function (key) {
|
|
|
2497
2677
|
* @return {Promise<Number>} 删除的成员数量
|
|
2498
2678
|
*/
|
|
2499
2679
|
MongoDB.prototype.zrem = async function (key, member) {
|
|
2680
|
+
// 参数校验
|
|
2681
|
+
if (typeof key !== 'string' || !key) {
|
|
2682
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2500
2685
|
try {
|
|
2501
2686
|
await this._ensureConnected();
|
|
2502
2687
|
const item = await this.findOne({
|
|
@@ -2516,7 +2701,7 @@ MongoDB.prototype.zrem = async function (key, member) {
|
|
|
2516
2701
|
|
|
2517
2702
|
return removedCount;
|
|
2518
2703
|
} catch (error) {
|
|
2519
|
-
|
|
2704
|
+
this.logger('error', '有序集合删除成员失败:', error);
|
|
2520
2705
|
return 0;
|
|
2521
2706
|
}
|
|
2522
2707
|
};
|
|
@@ -2528,6 +2713,11 @@ MongoDB.prototype.zrem = async function (key, member) {
|
|
|
2528
2713
|
* @return {Promise<Number|null>} 分数
|
|
2529
2714
|
*/
|
|
2530
2715
|
MongoDB.prototype.zscore = async function (key, member) {
|
|
2716
|
+
// 参数校验
|
|
2717
|
+
if (typeof key !== 'string' || !key) {
|
|
2718
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2531
2721
|
try {
|
|
2532
2722
|
await this._ensureConnected();
|
|
2533
2723
|
const item = await this.findOne({
|
|
@@ -2541,7 +2731,7 @@ MongoDB.prototype.zscore = async function (key, member) {
|
|
|
2541
2731
|
const found = item.value.find(item => JSON.stringify(item.member) === memberStr);
|
|
2542
2732
|
return found ? found.score : null;
|
|
2543
2733
|
} catch (error) {
|
|
2544
|
-
|
|
2734
|
+
this.logger('error', '获取成员分数失败:', error);
|
|
2545
2735
|
return null;
|
|
2546
2736
|
}
|
|
2547
2737
|
};
|
|
@@ -2552,6 +2742,11 @@ MongoDB.prototype.zscore = async function (key, member) {
|
|
|
2552
2742
|
* @return {Promise<any|null>} 弹出的元素
|
|
2553
2743
|
*/
|
|
2554
2744
|
MongoDB.prototype.lpop = async function (key) {
|
|
2745
|
+
// 参数校验
|
|
2746
|
+
if (typeof key !== 'string' || !key) {
|
|
2747
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2555
2750
|
try {
|
|
2556
2751
|
await this._ensureConnected();
|
|
2557
2752
|
const item = await this.findOne({
|
|
@@ -2569,7 +2764,7 @@ MongoDB.prototype.lpop = async function (key) {
|
|
|
2569
2764
|
});
|
|
2570
2765
|
return popped;
|
|
2571
2766
|
} catch (error) {
|
|
2572
|
-
|
|
2767
|
+
this.logger('error', '列表弹出头部元素失败:', error);
|
|
2573
2768
|
return null;
|
|
2574
2769
|
}
|
|
2575
2770
|
};
|
|
@@ -2580,6 +2775,11 @@ MongoDB.prototype.lpop = async function (key) {
|
|
|
2580
2775
|
* @return {Promise<any|null>} 弹出的元素
|
|
2581
2776
|
*/
|
|
2582
2777
|
MongoDB.prototype.rpop = async function (key) {
|
|
2778
|
+
// 参数校验
|
|
2779
|
+
if (typeof key !== 'string' || !key) {
|
|
2780
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2583
2783
|
try {
|
|
2584
2784
|
await this._ensureConnected();
|
|
2585
2785
|
const item = await this.findOne({
|
|
@@ -2597,7 +2797,7 @@ MongoDB.prototype.rpop = async function (key) {
|
|
|
2597
2797
|
});
|
|
2598
2798
|
return popped;
|
|
2599
2799
|
} catch (error) {
|
|
2600
|
-
|
|
2800
|
+
this.logger('error', '列表弹出尾部元素失败:', error);
|
|
2601
2801
|
return null;
|
|
2602
2802
|
}
|
|
2603
2803
|
};
|
|
@@ -2608,6 +2808,11 @@ MongoDB.prototype.rpop = async function (key) {
|
|
|
2608
2808
|
* @return {Promise<Array>} 成员数组
|
|
2609
2809
|
*/
|
|
2610
2810
|
MongoDB.prototype.smembers = async function (key) {
|
|
2811
|
+
// 参数校验
|
|
2812
|
+
if (typeof key !== 'string' || !key) {
|
|
2813
|
+
throw new TypeError('key必须是有效的字符串');
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2611
2816
|
try {
|
|
2612
2817
|
await this._ensureConnected();
|
|
2613
2818
|
const item = await this.findOne({
|
|
@@ -2627,7 +2832,7 @@ MongoDB.prototype.smembers = async function (key) {
|
|
|
2627
2832
|
});
|
|
2628
2833
|
return Array.from(uniqueMap.values());
|
|
2629
2834
|
} catch (error) {
|
|
2630
|
-
|
|
2835
|
+
this.logger('error', '获取集合所有成员失败:', error);
|
|
2631
2836
|
return [];
|
|
2632
2837
|
}
|
|
2633
2838
|
};
|
|
@@ -2648,7 +2853,7 @@ MongoDB.prototype.findOne = async function (query, options = {}) {
|
|
|
2648
2853
|
// 不需要额外的sanitize,MongoDB驱动会处理
|
|
2649
2854
|
return await this.db.collection(this.table).findOne(query, options);
|
|
2650
2855
|
} catch (error) {
|
|
2651
|
-
|
|
2856
|
+
this.logger('error', '查询单条数据失败:', error);
|
|
2652
2857
|
return null;
|
|
2653
2858
|
}
|
|
2654
2859
|
};
|
|
@@ -2658,11 +2863,31 @@ MongoDB.prototype.findOne = async function (query, options = {}) {
|
|
|
2658
2863
|
*/
|
|
2659
2864
|
MongoDB.prototype.setUrl = function () {
|
|
2660
2865
|
var url = "mongodb://";
|
|
2866
|
+
if (this.config.user) {
|
|
2867
|
+
url += encodeURIComponent(this.config.user);
|
|
2868
|
+
}
|
|
2661
2869
|
if (this.config.password) {
|
|
2662
|
-
url +=
|
|
2870
|
+
url += ':' + encodeURIComponent(this.config.password)
|
|
2871
|
+
}
|
|
2872
|
+
if (this.config.user || this.config.password) {
|
|
2873
|
+
url += '@'
|
|
2663
2874
|
}
|
|
2664
2875
|
url += this.config.host + ":" + this.config.port + "/";
|
|
2665
|
-
|
|
2876
|
+
url += this.config.database;
|
|
2877
|
+
|
|
2878
|
+
// 添加连接参数到连接字符串
|
|
2879
|
+
var params = [];
|
|
2880
|
+
if (this.config.min_pool_size) params.push('minPoolSize=' + this.config.min_pool_size);
|
|
2881
|
+
if (this.config.max_pool_size) params.push('maxPoolSize=' + this.config.max_pool_size);
|
|
2882
|
+
if (this.config.connect_timeout_ms) params.push('connectTimeoutMS=' + this.config.connect_timeout_ms);
|
|
2883
|
+
if (this.config.server_selection_timeout_ms) params.push('serverSelectionTimeoutMS=' + this.config.server_selection_timeout_ms);
|
|
2884
|
+
if (this.config.retry_writes !== undefined) params.push('retryWrites=' + (this.config.retry_writes ? 'true' : 'false'));
|
|
2885
|
+
|
|
2886
|
+
if (params.length > 0) {
|
|
2887
|
+
url += '?' + params.join('&');
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
return url;
|
|
2666
2891
|
};
|
|
2667
2892
|
|
|
2668
2893
|
/**
|
|
@@ -2670,34 +2895,32 @@ MongoDB.prototype.setUrl = function () {
|
|
|
2670
2895
|
* @return {Promise<Boolean>} 连接成功返回true, 失败抛出错误
|
|
2671
2896
|
*/
|
|
2672
2897
|
MongoDB.prototype.open = async function () {
|
|
2673
|
-
|
|
2674
|
-
this.setUrl();
|
|
2675
|
-
}
|
|
2898
|
+
|
|
2676
2899
|
if (!this.conn) {
|
|
2677
2900
|
return await this._withRetry(async () => {
|
|
2678
2901
|
try {
|
|
2679
|
-
|
|
2902
|
+
// 新版本MongoDB驱动只接受连接字符串,不再支持配置对象
|
|
2903
|
+
this.conn = await MongoClient.connect(this.setUrl());
|
|
2680
2904
|
this.db = this.conn.db(this.config.database);
|
|
2681
2905
|
this.connected = true;
|
|
2682
2906
|
|
|
2683
2907
|
// 设置连接事件监听
|
|
2684
2908
|
this.conn.on('error', (err) => {
|
|
2685
|
-
|
|
2909
|
+
this.logger('error', '连接错误:', err);
|
|
2686
2910
|
this.connected = false;
|
|
2687
2911
|
});
|
|
2688
2912
|
|
|
2689
2913
|
this.conn.on('close', () => {
|
|
2690
|
-
|
|
2914
|
+
this.logger('warn', '连接已关闭');
|
|
2691
2915
|
this.connected = false;
|
|
2692
2916
|
});
|
|
2693
2917
|
|
|
2694
|
-
|
|
2695
|
-
|
|
2918
|
+
this.logger('info',
|
|
2919
|
+
`成功连接到 ${this.config.host}:${this.config.port}/${this.config.database}`
|
|
2696
2920
|
);
|
|
2697
2921
|
return true;
|
|
2698
2922
|
} catch (error) {
|
|
2699
|
-
|
|
2700
|
-
throw error;
|
|
2923
|
+
this.logger('error', 'MongoDB连接失败:', error);
|
|
2701
2924
|
}
|
|
2702
2925
|
}, '数据库连接');
|
|
2703
2926
|
}
|
|
@@ -2709,8 +2932,8 @@ MongoDB.prototype.open = async function () {
|
|
|
2709
2932
|
*/
|
|
2710
2933
|
MongoDB.prototype.close = async function () {
|
|
2711
2934
|
if (this.conn) {
|
|
2712
|
-
|
|
2713
|
-
await this.conn.close().catch(err =>
|
|
2935
|
+
this.logger('info', `关闭连接`);
|
|
2936
|
+
await this.conn.close().catch(err => this.logger('error', '关闭MongoDB连接时出错:', err));
|
|
2714
2937
|
this.conn = null;
|
|
2715
2938
|
this.db = null;
|
|
2716
2939
|
this.connected = false;
|
|
@@ -2723,6 +2946,11 @@ MongoDB.prototype.close = async function () {
|
|
|
2723
2946
|
* @return {Promise|Object} 执行结果
|
|
2724
2947
|
*/
|
|
2725
2948
|
MongoDB.prototype.addTable = async function (table) {
|
|
2949
|
+
// 参数校验
|
|
2950
|
+
if (typeof table !== 'string' || !table) {
|
|
2951
|
+
throw new TypeError('table必须是有效的字符串');
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2726
2954
|
await this._ensureConnected();
|
|
2727
2955
|
if (table) {
|
|
2728
2956
|
this.table = table;
|
|
@@ -2739,19 +2967,24 @@ MongoDB.prototype.addTable = async function (table) {
|
|
|
2739
2967
|
* @returns {Promise<Object>} 创建索引的结果
|
|
2740
2968
|
*/
|
|
2741
2969
|
MongoDB.prototype.createIndex = async function (keys, options = {}) {
|
|
2970
|
+
// 参数校验
|
|
2971
|
+
if (typeof keys !== 'object' || keys === null || Array.isArray(keys)) {
|
|
2972
|
+
throw new TypeError('keys必须是非空对象');
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2742
2975
|
await this._ensureConnected();
|
|
2743
2976
|
try {
|
|
2744
2977
|
if (!this.db || !this.table) {
|
|
2745
2978
|
throw new Error('数据库未连接或未指定表名');
|
|
2746
2979
|
}
|
|
2747
2980
|
|
|
2748
|
-
|
|
2749
|
-
|
|
2981
|
+
this.logger('info',
|
|
2982
|
+
`创建索引: ${this.table}, keys: ${JSON.stringify(keys)}, options: ${JSON.stringify(options)}`
|
|
2750
2983
|
);
|
|
2751
2984
|
|
|
2752
2985
|
return await this.db.collection(this.table).createIndex(keys, options);
|
|
2753
2986
|
} catch (error) {
|
|
2754
|
-
|
|
2987
|
+
this.logger('error', `创建索引失败: ${error.message}`);
|
|
2755
2988
|
throw error;
|
|
2756
2989
|
}
|
|
2757
2990
|
};
|
|
@@ -2763,6 +2996,14 @@ MongoDB.prototype.createIndex = async function (keys, options = {}) {
|
|
|
2763
2996
|
* @returns {Promise<Object>} 创建索引的结果
|
|
2764
2997
|
*/
|
|
2765
2998
|
MongoDB.prototype.createTTLIndex = async function (keys, expireAfterSeconds) {
|
|
2999
|
+
// 参数校验
|
|
3000
|
+
if (typeof keys !== 'object' || keys === null || Array.isArray(keys)) {
|
|
3001
|
+
throw new TypeError('keys必须是非空对象');
|
|
3002
|
+
}
|
|
3003
|
+
if (typeof expireAfterSeconds !== 'number' || expireAfterSeconds < 0) {
|
|
3004
|
+
throw new TypeError('expireAfterSeconds必须是非负数');
|
|
3005
|
+
}
|
|
3006
|
+
|
|
2766
3007
|
await this._ensureConnected();
|
|
2767
3008
|
try {
|
|
2768
3009
|
if (!this.db || !this.table) {
|
|
@@ -2774,12 +3015,12 @@ MongoDB.prototype.createTTLIndex = async function (keys, expireAfterSeconds) {
|
|
|
2774
3015
|
expireAfterSeconds: expireAfterSeconds
|
|
2775
3016
|
};
|
|
2776
3017
|
|
|
2777
|
-
|
|
2778
|
-
|
|
3018
|
+
this.logger('info',
|
|
3019
|
+
`创建TTL索引: ${this.table}, keys: ${JSON.stringify(keys)}, 过期时间: ${expireAfterSeconds}秒`);
|
|
2779
3020
|
|
|
2780
3021
|
return await this.db.collection(this.table).createIndex(keys, options);
|
|
2781
3022
|
} catch (error) {
|
|
2782
|
-
|
|
3023
|
+
this.logger('error', `创建TTL索引失败: ${error.message}`);
|
|
2783
3024
|
throw error;
|
|
2784
3025
|
}
|
|
2785
3026
|
};
|
|
@@ -2791,16 +3032,16 @@ MongoDB.prototype.createTTLIndex = async function (keys, expireAfterSeconds) {
|
|
|
2791
3032
|
MongoDB.prototype.getIndexes = async function () {
|
|
2792
3033
|
await this._ensureConnected();
|
|
2793
3034
|
try {
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
3035
|
+
if (!this.table) {
|
|
3036
|
+
throw new Error('未指定表名');
|
|
3037
|
+
}
|
|
2797
3038
|
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3039
|
+
this.logger('info', `获取索引: ${this.table}`);
|
|
3040
|
+
return await this.db.collection(this.table).indexes();
|
|
3041
|
+
} catch (error) {
|
|
3042
|
+
this.logger('error', `[getIndexes] 获取索引失败: ${error.message}`);
|
|
3043
|
+
return [];
|
|
3044
|
+
}
|
|
2804
3045
|
};
|
|
2805
3046
|
|
|
2806
3047
|
/**
|
|
@@ -2811,17 +3052,17 @@ MongoDB.prototype.getIndexes = async function () {
|
|
|
2811
3052
|
MongoDB.prototype.dropIndex = async function (indexName) {
|
|
2812
3053
|
await this._ensureConnected();
|
|
2813
3054
|
if (!this.table) {
|
|
2814
|
-
throw new
|
|
3055
|
+
throw new TypeError('未指定表名');
|
|
2815
3056
|
}
|
|
2816
3057
|
if (!indexName) {
|
|
2817
|
-
throw new
|
|
3058
|
+
throw new TypeError('索引名称不能为空');
|
|
2818
3059
|
}
|
|
2819
3060
|
try {
|
|
2820
|
-
|
|
3061
|
+
this.logger('info', `[dropIndex] 删除索引: ${this.table}, 索引名: ${indexName}`);
|
|
2821
3062
|
await this.db.collection(this.table).dropIndex(indexName);
|
|
2822
3063
|
return true;
|
|
2823
3064
|
} catch (error) {
|
|
2824
|
-
|
|
3065
|
+
this.logger('error', `[dropIndex] 删除索引失败: ${error.message}`);
|
|
2825
3066
|
throw error;
|
|
2826
3067
|
}
|
|
2827
3068
|
};
|
|
@@ -2836,11 +3077,11 @@ MongoDB.prototype.dropTable = async function () {
|
|
|
2836
3077
|
throw new Error('未指定表名');
|
|
2837
3078
|
}
|
|
2838
3079
|
try {
|
|
2839
|
-
|
|
3080
|
+
this.logger('info', `[dropTable] 删除集合: ${this.table}`);
|
|
2840
3081
|
await this.db.collection(this.table).drop();
|
|
2841
3082
|
return true;
|
|
2842
3083
|
} catch (error) {
|
|
2843
|
-
|
|
3084
|
+
this.logger('error', `[dropTable] 删除集合失败: ${error.message}`);
|
|
2844
3085
|
throw error;
|
|
2845
3086
|
}
|
|
2846
3087
|
};
|
|
@@ -2854,7 +3095,7 @@ MongoDB.prototype.addObj = async function (obj) {
|
|
|
2854
3095
|
await this._ensureConnected();
|
|
2855
3096
|
try {
|
|
2856
3097
|
// 触发前置事件
|
|
2857
|
-
this.emit('
|
|
3098
|
+
this.emit('addObj:before', {
|
|
2858
3099
|
table: this.table,
|
|
2859
3100
|
data: obj
|
|
2860
3101
|
});
|
|
@@ -2863,7 +3104,7 @@ MongoDB.prototype.addObj = async function (obj) {
|
|
|
2863
3104
|
const result = await this.db.collection(this.table).insertOne(obj);
|
|
2864
3105
|
|
|
2865
3106
|
// 触发后置事件
|
|
2866
|
-
this.emit('
|
|
3107
|
+
this.emit('addObj:after', {
|
|
2867
3108
|
table: this.table,
|
|
2868
3109
|
data: obj,
|
|
2869
3110
|
result
|
|
@@ -2872,7 +3113,7 @@ MongoDB.prototype.addObj = async function (obj) {
|
|
|
2872
3113
|
return result;
|
|
2873
3114
|
} catch (error) {
|
|
2874
3115
|
// 触发错误事件
|
|
2875
|
-
this.emit('
|
|
3116
|
+
this.emit('addObj:error', {
|
|
2876
3117
|
table: this.table,
|
|
2877
3118
|
data: obj,
|
|
2878
3119
|
error
|
|
@@ -2899,7 +3140,7 @@ MongoDB.prototype.get = async function (key) {
|
|
|
2899
3140
|
});
|
|
2900
3141
|
return result ? result.value : null;
|
|
2901
3142
|
} catch (error) {
|
|
2902
|
-
|
|
3143
|
+
this.logger('error', `获取键值失败: ${error.message}`);
|
|
2903
3144
|
return null;
|
|
2904
3145
|
}
|
|
2905
3146
|
};
|
|
@@ -2920,7 +3161,7 @@ MongoDB.prototype.setForList = async function (key, array, seconds = 0) {
|
|
|
2920
3161
|
|
|
2921
3162
|
// 确保array是数组类型
|
|
2922
3163
|
if (!Array.isArray(array)) {
|
|
2923
|
-
throw new
|
|
3164
|
+
throw new TypeError('value必须是数组类型');
|
|
2924
3165
|
}
|
|
2925
3166
|
|
|
2926
3167
|
// 触发前置事件,允许修改或阻止操作
|
|
@@ -2930,10 +3171,10 @@ MongoDB.prototype.setForList = async function (key, array, seconds = 0) {
|
|
|
2930
3171
|
ttl: seconds,
|
|
2931
3172
|
cancel: false
|
|
2932
3173
|
};
|
|
2933
|
-
this.emit('
|
|
3174
|
+
this.emit('setForList:before', beforeEventData);
|
|
2934
3175
|
|
|
2935
3176
|
if (beforeEventData.cancel) {
|
|
2936
|
-
|
|
3177
|
+
this.logger('debug', `[setForList] setForList操作被事件处理器取消 [${key}]`);
|
|
2937
3178
|
return 0;
|
|
2938
3179
|
}
|
|
2939
3180
|
|
|
@@ -2951,7 +3192,7 @@ MongoDB.prototype.setForList = async function (key, array, seconds = 0) {
|
|
|
2951
3192
|
const length = finalValue.length;
|
|
2952
3193
|
|
|
2953
3194
|
// 触发后置事件
|
|
2954
|
-
this.emit('
|
|
3195
|
+
this.emit('setForList:after', {
|
|
2955
3196
|
key: finalKey,
|
|
2956
3197
|
value: finalValue,
|
|
2957
3198
|
ttl: finalSeconds,
|
|
@@ -2960,12 +3201,12 @@ MongoDB.prototype.setForList = async function (key, array, seconds = 0) {
|
|
|
2960
3201
|
});
|
|
2961
3202
|
return length;
|
|
2962
3203
|
} catch (error) {
|
|
2963
|
-
this.emit('
|
|
3204
|
+
this.emit('setForList:error', {
|
|
2964
3205
|
key,
|
|
2965
3206
|
value: array,
|
|
2966
3207
|
error
|
|
2967
3208
|
});
|
|
2968
|
-
|
|
3209
|
+
this.logger('error', `[setForList] setForList操作失败: ${error.message}`);
|
|
2969
3210
|
return 0;
|
|
2970
3211
|
}
|
|
2971
3212
|
};
|
|
@@ -2991,10 +3232,10 @@ MongoDB.prototype.addForList = async function (key, value, seconds = 0) {
|
|
|
2991
3232
|
ttl: seconds,
|
|
2992
3233
|
cancel: false
|
|
2993
3234
|
};
|
|
2994
|
-
this.emit('
|
|
3235
|
+
this.emit('addForList:before', beforeEventData);
|
|
2995
3236
|
|
|
2996
3237
|
if (beforeEventData.cancel) {
|
|
2997
|
-
|
|
3238
|
+
this.logger('debug', `addForList操作被事件处理器取消 [${key}]`);
|
|
2998
3239
|
return 0;
|
|
2999
3240
|
}
|
|
3000
3241
|
|
|
@@ -3021,7 +3262,7 @@ MongoDB.prototype.addForList = async function (key, value, seconds = 0) {
|
|
|
3021
3262
|
const length = currentArray.length;
|
|
3022
3263
|
|
|
3023
3264
|
// 触发后置事件
|
|
3024
|
-
this.emit('
|
|
3265
|
+
this.emit('addForList:after', {
|
|
3025
3266
|
key: finalKey,
|
|
3026
3267
|
value: finalValue,
|
|
3027
3268
|
ttl: finalSeconds,
|
|
@@ -3030,12 +3271,12 @@ MongoDB.prototype.addForList = async function (key, value, seconds = 0) {
|
|
|
3030
3271
|
});
|
|
3031
3272
|
return length;
|
|
3032
3273
|
} catch (error) {
|
|
3033
|
-
this.emit('
|
|
3274
|
+
this.emit('addForList:error', {
|
|
3034
3275
|
key,
|
|
3035
3276
|
value,
|
|
3036
3277
|
error
|
|
3037
3278
|
});
|
|
3038
|
-
|
|
3279
|
+
this.logger('error', `addForList操作失败: ${error.message}`);
|
|
3039
3280
|
return 0;
|
|
3040
3281
|
}
|
|
3041
3282
|
};
|
|
@@ -3068,7 +3309,7 @@ MongoDB.prototype.hasForList = async function (key, value) {
|
|
|
3068
3309
|
const valueStr = JSON.stringify(value);
|
|
3069
3310
|
return array.some(item => JSON.stringify(item) === valueStr);
|
|
3070
3311
|
} catch (error) {
|
|
3071
|
-
|
|
3312
|
+
this.logger('error', `hasForList操作失败: ${error.message}`);
|
|
3072
3313
|
return false;
|
|
3073
3314
|
}
|
|
3074
3315
|
};
|
|
@@ -3106,7 +3347,7 @@ MongoDB.prototype.getForList = async function (key, start = 0, stop = -1) {
|
|
|
3106
3347
|
|
|
3107
3348
|
return result;
|
|
3108
3349
|
} catch (error) {
|
|
3109
|
-
|
|
3350
|
+
this.logger('error', `getForList操作失败: ${error.message}`);
|
|
3110
3351
|
return [];
|
|
3111
3352
|
}
|
|
3112
3353
|
};
|
|
@@ -3129,7 +3370,7 @@ MongoDB.prototype.clearForList = async function (key) {
|
|
|
3129
3370
|
// 使用set方法直接设置为空数组,与其他模块行为一致
|
|
3130
3371
|
return await this.set(key, []);
|
|
3131
3372
|
} catch (error) {
|
|
3132
|
-
|
|
3373
|
+
this.logger('error', `clearForList操作失败: ${error.message}`);
|
|
3133
3374
|
return false;
|
|
3134
3375
|
}
|
|
3135
3376
|
};
|
|
@@ -3141,7 +3382,7 @@ MongoDB.prototype.has = async function (key) {
|
|
|
3141
3382
|
const exists = await this.exists(key);
|
|
3142
3383
|
return exists > 0;
|
|
3143
3384
|
} catch (error) {
|
|
3144
|
-
|
|
3385
|
+
this.logger('error', `检查键是否存在失败: ${error.message}`);
|
|
3145
3386
|
throw error;
|
|
3146
3387
|
}
|
|
3147
3388
|
};
|
|
@@ -3149,6 +3390,11 @@ MongoDB.prototype.has = async function (key) {
|
|
|
3149
3390
|
MongoDB.prototype.exists = async function (key) {
|
|
3150
3391
|
await this._ensureConnected();
|
|
3151
3392
|
try {
|
|
3393
|
+
// 参数验证
|
|
3394
|
+
if (!key) {
|
|
3395
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3152
3398
|
// 检查单个键的情况
|
|
3153
3399
|
if (typeof key === 'string') {
|
|
3154
3400
|
const result = await this.db.collection(this.table).findOne({
|
|
@@ -3165,7 +3411,7 @@ MongoDB.prototype.exists = async function (key) {
|
|
|
3165
3411
|
// 验证数组中的每个元素是否都是非空字符串
|
|
3166
3412
|
for (const k of key) {
|
|
3167
3413
|
if (!k || typeof k !== 'string') {
|
|
3168
|
-
throw new
|
|
3414
|
+
throw new TypeError('key数组中的每个元素必须是非空字符串');
|
|
3169
3415
|
}
|
|
3170
3416
|
}
|
|
3171
3417
|
|
|
@@ -3177,10 +3423,10 @@ MongoDB.prototype.exists = async function (key) {
|
|
|
3177
3423
|
const count = await this.db.collection(this.table).countDocuments(filter);
|
|
3178
3424
|
return count;
|
|
3179
3425
|
} else {
|
|
3180
|
-
throw new
|
|
3426
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
3181
3427
|
}
|
|
3182
3428
|
} catch (error) {
|
|
3183
|
-
|
|
3429
|
+
this.logger('error', `检查键是否存在失败: ${error.message}`);
|
|
3184
3430
|
throw error;
|
|
3185
3431
|
}
|
|
3186
3432
|
};
|
|
@@ -3191,44 +3437,41 @@ MongoDB.prototype.exists = async function (key) {
|
|
|
3191
3437
|
* @return {Promise<Boolean>} 是否删除成功
|
|
3192
3438
|
*/
|
|
3193
3439
|
MongoDB.prototype.del = async function (key) {
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
$.log.error('[MongoDB] 参数错误: key必须是非空字符串或非空字符串数组');
|
|
3199
|
-
return false;
|
|
3200
|
-
}
|
|
3440
|
+
// 参数验证
|
|
3441
|
+
if (!key) {
|
|
3442
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
3443
|
+
}
|
|
3201
3444
|
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
return false;
|
|
3207
|
-
}
|
|
3445
|
+
// 如果是单个键,验证是否为非空字符串
|
|
3446
|
+
if (typeof key === 'string') {
|
|
3447
|
+
if (!key) {
|
|
3448
|
+
throw new TypeError('key必须是非空字符串');
|
|
3208
3449
|
}
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
}
|
|
3450
|
+
}
|
|
3451
|
+
// 如果是数组,验证每个元素是否为非空字符串
|
|
3452
|
+
else if (Array.isArray(key)) {
|
|
3453
|
+
for (const k of key) {
|
|
3454
|
+
if (!k || typeof k !== 'string') {
|
|
3455
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
3216
3456
|
}
|
|
3217
|
-
} else {
|
|
3218
|
-
$.log.error('[MongoDB] 参数错误: key必须是非空字符串或非空字符串数组');
|
|
3219
|
-
return false;
|
|
3220
3457
|
}
|
|
3458
|
+
} else {
|
|
3459
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
3460
|
+
}
|
|
3461
|
+
|
|
3462
|
+
await this._ensureConnected();
|
|
3463
|
+
try {
|
|
3221
3464
|
|
|
3222
3465
|
// 触发前置事件,允许修改或阻止操作
|
|
3223
3466
|
const beforeEventData = {
|
|
3224
3467
|
key,
|
|
3225
3468
|
cancel: false
|
|
3226
3469
|
};
|
|
3227
|
-
this.emit('
|
|
3470
|
+
this.emit('del:before', beforeEventData);
|
|
3228
3471
|
|
|
3229
3472
|
// 如果事件处理器标记为取消,则返回false
|
|
3230
3473
|
if (beforeEventData.cancel) {
|
|
3231
|
-
|
|
3474
|
+
this.logger('debug', `del操作被事件处理器取消 [${key}]`);
|
|
3232
3475
|
return false;
|
|
3233
3476
|
}
|
|
3234
3477
|
|
|
@@ -3265,7 +3508,7 @@ MongoDB.prototype.del = async function (key) {
|
|
|
3265
3508
|
}
|
|
3266
3509
|
|
|
3267
3510
|
// 触发后置事件
|
|
3268
|
-
this.emit('
|
|
3511
|
+
this.emit('del:after', {
|
|
3269
3512
|
key: finalKey,
|
|
3270
3513
|
success,
|
|
3271
3514
|
deleted
|
|
@@ -3274,11 +3517,11 @@ MongoDB.prototype.del = async function (key) {
|
|
|
3274
3517
|
return success;
|
|
3275
3518
|
} catch (error) {
|
|
3276
3519
|
// 触发错误事件
|
|
3277
|
-
this.emit('
|
|
3520
|
+
this.emit('del:error', {
|
|
3278
3521
|
key,
|
|
3279
3522
|
error: error
|
|
3280
3523
|
});
|
|
3281
|
-
|
|
3524
|
+
this.logger('error', '删除缓存失败:', error);
|
|
3282
3525
|
return false;
|
|
3283
3526
|
}
|
|
3284
3527
|
};
|
|
@@ -3300,11 +3543,11 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
3300
3543
|
ttl: seconds,
|
|
3301
3544
|
cancel: false
|
|
3302
3545
|
};
|
|
3303
|
-
this.emit('
|
|
3546
|
+
this.emit('add:before', beforeEventData);
|
|
3304
3547
|
|
|
3305
3548
|
// 如果事件处理器标记为取消,则返回false
|
|
3306
3549
|
if (beforeEventData.cancel) {
|
|
3307
|
-
|
|
3550
|
+
this.logger('debug', `add操作被事件处理器取消 [${key}]`);
|
|
3308
3551
|
return false;
|
|
3309
3552
|
}
|
|
3310
3553
|
|
|
@@ -3321,7 +3564,7 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
3321
3564
|
});
|
|
3322
3565
|
if (exists) {
|
|
3323
3566
|
// 键已存在时触发后置事件,但返回false
|
|
3324
|
-
this.emit('
|
|
3567
|
+
this.emit('add:after', {
|
|
3325
3568
|
key: finalKey,
|
|
3326
3569
|
value: finalValue,
|
|
3327
3570
|
ttl: finalSeconds,
|
|
@@ -3346,7 +3589,7 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
3346
3589
|
const success = result.acknowledged;
|
|
3347
3590
|
|
|
3348
3591
|
// 触发后置事件
|
|
3349
|
-
this.emit('
|
|
3592
|
+
this.emit('add:after', {
|
|
3350
3593
|
key: finalKey,
|
|
3351
3594
|
value: finalValue,
|
|
3352
3595
|
ttl: finalSeconds,
|
|
@@ -3356,13 +3599,13 @@ MongoDB.prototype.add = async function (key, value, seconds) {
|
|
|
3356
3599
|
return success;
|
|
3357
3600
|
} catch (error) {
|
|
3358
3601
|
// 触发错误事件
|
|
3359
|
-
this.emit('
|
|
3602
|
+
this.emit('add:error', {
|
|
3360
3603
|
key,
|
|
3361
3604
|
value,
|
|
3362
3605
|
ttl: seconds,
|
|
3363
3606
|
error
|
|
3364
3607
|
});
|
|
3365
|
-
|
|
3608
|
+
this.logger('error', `添加键值失败: ${error.message}`);
|
|
3366
3609
|
return false;
|
|
3367
3610
|
}
|
|
3368
3611
|
};
|
|
@@ -3378,7 +3621,7 @@ MongoDB.prototype.set = async function (key, value, seconds) {
|
|
|
3378
3621
|
try {
|
|
3379
3622
|
// 键名必须是非空字符串
|
|
3380
3623
|
if (!key || typeof key !== 'string') {
|
|
3381
|
-
|
|
3624
|
+
this.logger('error', '参数错误: key必须是非空字符串');
|
|
3382
3625
|
return false;
|
|
3383
3626
|
}
|
|
3384
3627
|
|
|
@@ -3389,11 +3632,11 @@ MongoDB.prototype.set = async function (key, value, seconds) {
|
|
|
3389
3632
|
ttl: seconds,
|
|
3390
3633
|
cancel: false
|
|
3391
3634
|
};
|
|
3392
|
-
this.emit('
|
|
3635
|
+
this.emit('set:before', beforeEventData);
|
|
3393
3636
|
|
|
3394
3637
|
// 如果事件处理器标记为取消,则返回false
|
|
3395
3638
|
if (beforeEventData.cancel) {
|
|
3396
|
-
|
|
3639
|
+
this.logger('debug', `set操作被事件处理器取消 [${key}]`);
|
|
3397
3640
|
return false;
|
|
3398
3641
|
}
|
|
3399
3642
|
|
|
@@ -3432,7 +3675,7 @@ MongoDB.prototype.set = async function (key, value, seconds) {
|
|
|
3432
3675
|
);
|
|
3433
3676
|
|
|
3434
3677
|
// 触发后置事件
|
|
3435
|
-
this.emit('
|
|
3678
|
+
this.emit('set:after', {
|
|
3436
3679
|
key: finalKey,
|
|
3437
3680
|
value: finalValue,
|
|
3438
3681
|
ttl: finalSeconds,
|
|
@@ -3442,13 +3685,13 @@ MongoDB.prototype.set = async function (key, value, seconds) {
|
|
|
3442
3685
|
return result.acknowledged;
|
|
3443
3686
|
} catch (error) {
|
|
3444
3687
|
// 触发错误事件
|
|
3445
|
-
this.emit('
|
|
3688
|
+
this.emit('set:error', {
|
|
3446
3689
|
key,
|
|
3447
3690
|
value,
|
|
3448
3691
|
ttl: seconds,
|
|
3449
3692
|
error
|
|
3450
3693
|
});
|
|
3451
|
-
|
|
3694
|
+
this.logger('error', `设置键值失败: ${error.message}`);
|
|
3452
3695
|
return false;
|
|
3453
3696
|
}
|
|
3454
3697
|
};
|
|
@@ -3462,7 +3705,7 @@ MongoDB.prototype.addList = async function (list) {
|
|
|
3462
3705
|
await this._ensureConnected();
|
|
3463
3706
|
try {
|
|
3464
3707
|
// 触发前置事件
|
|
3465
|
-
this.emit('
|
|
3708
|
+
this.emit('addList:before', {
|
|
3466
3709
|
table: this.table,
|
|
3467
3710
|
data: list
|
|
3468
3711
|
});
|
|
@@ -3471,7 +3714,7 @@ MongoDB.prototype.addList = async function (list) {
|
|
|
3471
3714
|
const result = await this.db.collection(this.table).insertMany(list);
|
|
3472
3715
|
|
|
3473
3716
|
// 触发后置事件
|
|
3474
|
-
this.emit('
|
|
3717
|
+
this.emit('addList:after', {
|
|
3475
3718
|
table: this.table,
|
|
3476
3719
|
data: list,
|
|
3477
3720
|
result
|
|
@@ -3480,7 +3723,7 @@ MongoDB.prototype.addList = async function (list) {
|
|
|
3480
3723
|
return result;
|
|
3481
3724
|
} catch (error) {
|
|
3482
3725
|
// 触发错误事件
|
|
3483
|
-
this.emit('
|
|
3726
|
+
this.emit('addList:error', {
|
|
3484
3727
|
table: this.table,
|
|
3485
3728
|
data: list,
|
|
3486
3729
|
error
|
|
@@ -3503,7 +3746,7 @@ MongoDB.prototype.delete = async function (query) {
|
|
|
3503
3746
|
} : query;
|
|
3504
3747
|
|
|
3505
3748
|
// 触发前置事件
|
|
3506
|
-
this.emit('
|
|
3749
|
+
this.emit('delete:before', {
|
|
3507
3750
|
table: this.table,
|
|
3508
3751
|
query: safeQuery
|
|
3509
3752
|
});
|
|
@@ -3512,7 +3755,7 @@ MongoDB.prototype.delete = async function (query) {
|
|
|
3512
3755
|
const result = await this.db.collection(this.table).deleteMany(safeQuery);
|
|
3513
3756
|
|
|
3514
3757
|
// 触发后置事件
|
|
3515
|
-
this.emit('
|
|
3758
|
+
this.emit('delete:after', {
|
|
3516
3759
|
table: this.table,
|
|
3517
3760
|
query: safeQuery,
|
|
3518
3761
|
result
|
|
@@ -3521,7 +3764,7 @@ MongoDB.prototype.delete = async function (query) {
|
|
|
3521
3764
|
return result;
|
|
3522
3765
|
} catch (error) {
|
|
3523
3766
|
// 触发错误事件
|
|
3524
|
-
this.emit('
|
|
3767
|
+
this.emit('delete:error', {
|
|
3525
3768
|
table: this.table,
|
|
3526
3769
|
query,
|
|
3527
3770
|
error
|
|
@@ -3568,7 +3811,7 @@ MongoDB.prototype.setting = async function (query, body, options = {}) {
|
|
|
3568
3811
|
}, options);
|
|
3569
3812
|
|
|
3570
3813
|
// 触发前置事件
|
|
3571
|
-
this.emit('
|
|
3814
|
+
this.emit('setting:before', {
|
|
3572
3815
|
table: this.table,
|
|
3573
3816
|
query: safeQuery,
|
|
3574
3817
|
update: updateBody,
|
|
@@ -3579,7 +3822,7 @@ MongoDB.prototype.setting = async function (query, body, options = {}) {
|
|
|
3579
3822
|
const result = await this.db.collection(this.table).updateMany(safeQuery, updateBody, updateOptions);
|
|
3580
3823
|
|
|
3581
3824
|
// 触发后置事件
|
|
3582
|
-
this.emit('
|
|
3825
|
+
this.emit('setting:after', {
|
|
3583
3826
|
table: this.table,
|
|
3584
3827
|
query: safeQuery,
|
|
3585
3828
|
update: updateBody,
|
|
@@ -3591,7 +3834,7 @@ MongoDB.prototype.setting = async function (query, body, options = {}) {
|
|
|
3591
3834
|
return typeof query === 'string' ? result.modifiedCount > 0 : result;
|
|
3592
3835
|
} catch (error) {
|
|
3593
3836
|
// 触发错误事件
|
|
3594
|
-
this.emit('
|
|
3837
|
+
this.emit('setting:error', {
|
|
3595
3838
|
table: this.table,
|
|
3596
3839
|
query,
|
|
3597
3840
|
update: body,
|
|
@@ -3618,7 +3861,7 @@ MongoDB.prototype.find = async function (query, options = {}) {
|
|
|
3618
3861
|
const cursor = this.db.collection(this.table).find(safeQuery, options);
|
|
3619
3862
|
return await cursor.toArray();
|
|
3620
3863
|
} catch (error) {
|
|
3621
|
-
|
|
3864
|
+
this.logger('error', '查询失败:', error);
|
|
3622
3865
|
return [];
|
|
3623
3866
|
}
|
|
3624
3867
|
};
|
|
@@ -3635,7 +3878,7 @@ MongoDB.prototype.count = async function (query = {}) {
|
|
|
3635
3878
|
const safeQuery = this._sanitizeQuery(query);
|
|
3636
3879
|
return await this.db.collection(this.table).countDocuments(safeQuery);
|
|
3637
3880
|
} catch (error) {
|
|
3638
|
-
|
|
3881
|
+
this.logger('error', '计算文档数量失败:', error);
|
|
3639
3882
|
return 0;
|
|
3640
3883
|
}
|
|
3641
3884
|
};
|
|
@@ -3654,7 +3897,7 @@ MongoDB.prototype._sanitizeQuery = function (query) {
|
|
|
3654
3897
|
// 防止NoSQL注入,如 {$ne: null} 等操作符注入
|
|
3655
3898
|
if (key.startsWith('$') && typeof key === 'string' && !Array.isArray(value) && typeof value === 'object' &&
|
|
3656
3899
|
value !== null) {
|
|
3657
|
-
|
|
3900
|
+
this.logger('warn', '检测到可能的操作符注入尝试:', key);
|
|
3658
3901
|
continue;
|
|
3659
3902
|
}
|
|
3660
3903
|
sanitized[key] = value;
|
|
@@ -3674,7 +3917,7 @@ MongoDB.prototype.startTransaction = async function () {
|
|
|
3674
3917
|
session.startTransaction();
|
|
3675
3918
|
return session;
|
|
3676
3919
|
} catch (error) {
|
|
3677
|
-
|
|
3920
|
+
this.logger('error', '[startTransaction] 启动事务失败:', error);
|
|
3678
3921
|
throw error;
|
|
3679
3922
|
}
|
|
3680
3923
|
};
|
|
@@ -3689,7 +3932,7 @@ MongoDB.prototype.commitTransaction = async function (session) {
|
|
|
3689
3932
|
await session.commitTransaction();
|
|
3690
3933
|
await session.endSession();
|
|
3691
3934
|
} catch (error) {
|
|
3692
|
-
|
|
3935
|
+
this.logger('error', '[commitTransaction] 提交事务失败:', error);
|
|
3693
3936
|
throw error;
|
|
3694
3937
|
}
|
|
3695
3938
|
};
|
|
@@ -3704,7 +3947,7 @@ MongoDB.prototype.rollbackTransaction = async function (session) {
|
|
|
3704
3947
|
await session.abortTransaction();
|
|
3705
3948
|
await session.endSession();
|
|
3706
3949
|
} catch (error) {
|
|
3707
|
-
|
|
3950
|
+
this.logger('error', '[rollbackTransaction] 回滚事务失败:', error);
|
|
3708
3951
|
throw error;
|
|
3709
3952
|
}
|
|
3710
3953
|
};
|
|
@@ -3730,7 +3973,7 @@ if (!$.pool.mongoDB) {
|
|
|
3730
3973
|
* @param {Object} config 配置参数
|
|
3731
3974
|
* @return {Object} 返回一个MongoDB类实例
|
|
3732
3975
|
*/
|
|
3733
|
-
function
|
|
3976
|
+
function mongodbAdmin(scope, config) {
|
|
3734
3977
|
if (!scope) {
|
|
3735
3978
|
scope = 'sys';
|
|
3736
3979
|
}
|
|
@@ -3752,4 +3995,4 @@ function mongodb_admin(scope, config) {
|
|
|
3752
3995
|
/**
|
|
3753
3996
|
* @module 导出MongoDB管理器
|
|
3754
3997
|
*/
|
|
3755
|
-
exports.
|
|
3998
|
+
exports.mongodbAdmin = mongodbAdmin;
|