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