mm_mongodb 1.4.3 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +565 -231
  2. package/cache.js +2680 -173
  3. package/index.js +483 -64
  4. package/package.json +23 -16
  5. package/test.js +6 -8
package/index.js CHANGED
@@ -1,15 +1,23 @@
1
1
  /**
2
- * @fileOverview mongoDB帮助类函数
2
+ * @fileOverview MongoDB帮助类函数
3
3
  * @author <a href="http://qww.elins.cn">邱文武</a>
4
4
  * @version 1.2.1
5
5
  */
6
- require('mm_expand');
6
+ const eventEmitter = require('events');
7
+ require('mm_logs');
7
8
  const MongoClient = require('mongodb').MongoClient;
8
9
 
10
+ /**
11
+ * 确保全局$对象存在
12
+ */
13
+ if (!global.$) {
14
+ global.$ = {};
15
+ }
16
+
9
17
  /**
10
18
  * @description MongoDB帮助类
11
19
  */
12
- class MongoDB {
20
+ class MongoDB extends eventEmitter {
13
21
  /**
14
22
  * @description 创建MongoDB帮助类函数 (构造函数)
15
23
  * @param {String} scope 作用域
@@ -17,18 +25,15 @@ class MongoDB {
17
25
  * @constructor
18
26
  */
19
27
  constructor(scope, dir, config) {
28
+ super();
20
29
  // 作用域
21
- this.scope;
22
- if (scope) {
23
- this.scope = scope;
24
- } else {
25
- this.scope = $.val.scope + '';
26
- }
30
+ this.scope = scope || ($.val && $.val.scope ? String($.val.scope) : 'default');
27
31
  // 当前目录
28
- this.dir = __dirname;
29
- if (dir) {
30
- this.dir = dir;
31
- }
32
+ this.dir = dir || __dirname;
33
+
34
+ // 从环境变量加载配置
35
+ const envConfig = this._loadEnvConfig();
36
+
32
37
  this.config = Object.assign({
33
38
  // 服务器地址
34
39
  host: "localhost",
@@ -40,25 +45,36 @@ class MongoDB {
40
45
  user: "admin",
41
46
  // 密码
42
47
  password: "",
43
- // 附加选项
48
+ // 连接选项
44
49
  options: {
45
- // 使用新的url分析器
46
- useNewUrlParser: true,
47
- // 自动重连接
48
- // auto_reconnect: true,
49
- // 使用统一拓扑
50
- useUnifiedTopology: true,
51
- // useCreateIndex: true,
52
- // 连接池数
53
- // poolSize: 10
50
+ // 移除已废弃的选项
51
+ // 使用MongoDB驱动推荐的配置
52
+ // 连接池配置
53
+ minPoolSize: 5,
54
+ maxPoolSize: 20,
55
+ // 连接超时时间
56
+ connectTimeoutMS: 10000,
57
+ // 服务器选择超时
58
+ serverSelectionTimeoutMS: 5000,
59
+ // 重试策略
60
+ retryWrites: true
61
+ },
62
+ // 重试配置
63
+ retry: {
64
+ maxAttempts: 3,
65
+ delayMS: 1000
54
66
  }
55
- }, config);
67
+ }, envConfig, config);
68
+
69
+ // 验证配置
70
+ this._validateConfig();
71
+
56
72
  // 连接地址
57
- this.url;
73
+ this.url = null;
58
74
  // 数据库连接器
59
- this.conn;
75
+ this.conn = null;
60
76
  // 操作的数据库
61
- this.db;
77
+ this.db = null;
62
78
  // 表名
63
79
  this.table = "cache";
64
80
  /**
@@ -69,6 +85,74 @@ class MongoDB {
69
85
  * 每页显示条数
70
86
  */
71
87
  this.size = 0;
88
+ // 连接状态
89
+ this.connected = false;
90
+ }
91
+
92
+ /**
93
+ * @private
94
+ * @description 从环境变量加载配置
95
+ * @return {Object} 配置对象
96
+ */
97
+ _loadEnvConfig() {
98
+ const envConfig = {};
99
+
100
+ if (process.env.MONGODB_HOST) envConfig.host = process.env.MONGODB_HOST;
101
+ if (process.env.MONGODB_PORT) envConfig.port = parseInt(process.env.MONGODB_PORT, 10);
102
+ if (process.env.MONGODB_DATABASE) envConfig.database = process.env.MONGODB_DATABASE;
103
+ if (process.env.MONGODB_USER) envConfig.user = process.env.MONGODB_USER;
104
+ if (process.env.MONGODB_PASSWORD) envConfig.password = process.env.MONGODB_PASSWORD;
105
+
106
+ return envConfig;
107
+ }
108
+
109
+ /**
110
+ * @private
111
+ * @description 验证配置有效性
112
+ * @throws {Error} 配置无效时抛出错误
113
+ */
114
+ _validateConfig() {
115
+ if (!this.config.host || typeof this.config.host !== 'string') {
116
+ throw new Error('MongoDB配置无效:host必须是有效的字符串');
117
+ }
118
+
119
+ if (!Number.isInteger(this.config.port) || this.config.port < 1 || this.config.port > 65535) {
120
+ throw new Error('MongoDB配置无效:port必须是1-65535之间的整数');
121
+ }
122
+
123
+ if (!this.config.database || typeof this.config.database !== 'string') {
124
+ throw new Error('MongoDB配置无效:database必须是有效的字符串');
125
+ }
126
+ }
127
+
128
+ /**
129
+ * @private
130
+ * @description 执行带重试的操作
131
+ * @param {Function} operation 要执行的操作
132
+ * @param {String} operationName 操作名称
133
+ * @return {Promise} 操作结果
134
+ */
135
+ async _withRetry(operation, operationName) {
136
+ const maxAttempts = this.config.retry?.maxAttempts || 3;
137
+ const delayMS = this.config.retry?.delayMS || 1000;
138
+ let lastError;
139
+
140
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
141
+ try {
142
+ return await operation();
143
+ } catch (error) {
144
+ lastError = error;
145
+ $.log.error(`[MongoDB] ${operationName} 第${attempt}次尝试失败:`, error.message);
146
+
147
+ // 如果不是最后一次尝试,则等待后重试
148
+ if (attempt < maxAttempts) {
149
+ await new Promise(resolve => setTimeout(resolve, delayMS));
150
+ }
151
+ }
152
+ }
153
+
154
+ // 所有重试都失败,抛出最后一个错误
155
+ throw lastError;
72
156
  }
73
157
  }
74
158
 
@@ -76,49 +160,79 @@ class MongoDB {
76
160
  * @description 设置配置
77
161
  * @param {Object|String} cg 配置对象或配置路径
78
162
  */
79
- MongoDB.prototype.setConfig = function(cg) {
163
+ MongoDB.prototype.setConfig = function (cg) {
80
164
  var obj;
81
- if (typeof(cg) === "string") {
82
- obj = cg.loadJson(this.dir);
83
- } else {
165
+ if (typeof (cg) === "string") {
166
+ obj = cg.loadJson ? cg.loadJson(this.dir) : null;
167
+ } else if (cg) {
84
168
  obj = cg;
85
169
  }
86
- $.push(this.config, obj);
170
+ if (obj) {
171
+ $.push(this.config, obj);
172
+ // 设置新配置后重新验证
173
+ this._validateConfig();
174
+ }
87
175
  };
88
176
 
89
177
  /**
90
178
  * @description 设置Url
91
179
  */
92
- MongoDB.prototype.setUrl = function() {
180
+ MongoDB.prototype.setUrl = function () {
93
181
  var url = "mongodb://";
94
182
  if (this.config.password) {
95
- url += this.config.user + ':' + this.config.password + '@';
183
+ url += encodeURIComponent(this.config.user) + ':' + encodeURIComponent(this.config.password) + '@';
96
184
  }
97
185
  url += this.config.host + ":" + this.config.port + "/";
98
186
  this.url = url;
99
187
  };
100
188
 
101
189
  /**
102
- * @description 连接mongoDB数据库
103
- * @return {Boolean} 连接成功返回true, 失败返回false
190
+ * @description 连接MongoDB数据库
191
+ * @return {Promise<Boolean>} 连接成功返回true, 失败抛出错误
104
192
  */
105
- MongoDB.prototype.open = async function() {
193
+ MongoDB.prototype.open = async function () {
106
194
  if (!this.url) {
107
195
  this.setUrl();
108
196
  }
109
197
  if (!this.conn) {
110
- this.conn = await MongoClient.connect(this.url, this.config.options);
111
- this.db = this.conn.db(this.config.database);
198
+ return await this._withRetry(async () => {
199
+ try {
200
+ this.conn = await MongoClient.connect(this.url, this.config.options);
201
+ this.db = this.conn.db(this.config.database);
202
+ this.connected = true;
203
+
204
+ // 设置连接事件监听
205
+ this.conn.on('error', (err) => {
206
+ $.log.error('[MongoDB] 连接错误:', err);
207
+ this.connected = false;
208
+ });
209
+
210
+ this.conn.on('close', () => {
211
+ $.log.warn('[MongoDB] 连接已关闭');
212
+ this.connected = false;
213
+ });
214
+
215
+ $.log.info(`[MongoDB] 成功连接到 ${this.config.host}:${this.config.port}/${this.config.database}`);
216
+ return true;
217
+ } catch (error) {
218
+ $.log.error('[MongoDB] MongoDB连接失败:', error);
219
+ throw error;
220
+ }
221
+ }, '数据库连接');
112
222
  }
113
- return this.conn == true;
223
+ return true;
114
224
  };
115
225
 
116
226
  /**
117
227
  * 关闭数据库连接
118
228
  */
119
- MongoDB.prototype.close = function() {
229
+ MongoDB.prototype.close = async function () {
120
230
  if (this.conn) {
121
- this.conn.close();
231
+ $.log.info(`[MongoDB] 关闭连接`);
232
+ await this.conn.close().catch(err => $.log.error('[MongoDB] 关闭MongoDB连接时出错:', err));
233
+ this.conn = null;
234
+ this.db = null;
235
+ this.connected = false;
122
236
  }
123
237
  };
124
238
 
@@ -127,7 +241,7 @@ MongoDB.prototype.close = function() {
127
241
  * @param {Object} table 表名
128
242
  * @return {Promise|Object} 执行结果
129
243
  */
130
- MongoDB.prototype.addTable = function(table) {
244
+ MongoDB.prototype.addTable = function (table) {
131
245
  if (table) {
132
246
  this.table = table;
133
247
  } else {
@@ -136,13 +250,161 @@ MongoDB.prototype.addTable = function(table) {
136
250
  return this.db.createCollection(table);
137
251
  };
138
252
 
253
+ /**
254
+ * @description 创建TTL索引
255
+ * @param {String} table 表名
256
+ * @param {String} field 过期字段名
257
+ * @param {Number} expireAfterSeconds 过期时间(秒)
258
+ * @return {Promise<Object>} 执行结果
259
+ */
260
+ MongoDB.prototype.createTTLIndex = async function (table, field, expireAfterSeconds) {
261
+ if (!table) table = this.table;
262
+ return await this.db.collection(table).createIndex(
263
+ { [field]: 1 },
264
+ { expireAfterSeconds: expireAfterSeconds || 0 }
265
+ );
266
+ };
267
+
268
+ /**
269
+ * @description 创建普通索引
270
+ * @param {String} table 表名
271
+ * @param {Object} keys 索引字段对象
272
+ * @param {Object} options 索引选项
273
+ * @return {Promise<Object>} 执行结果
274
+ */
275
+ /**
276
+ * @description 创建索引
277
+ * @param {Object} keys 索引键配置 {field: 1或-1}
278
+ * @param {Object} options 索引选项
279
+ * @returns {Promise<Object>} 创建索引的结果
280
+ */
281
+ MongoDB.prototype.createIndex = async function (keys, options = {}) {
282
+ try {
283
+ if (!this.db || !this.table) {
284
+ throw new Error('数据库未连接或未指定表名');
285
+ }
286
+
287
+ $.log.info(`[MongoDB] 创建索引: ${this.table}, keys: ${JSON.stringify(keys)}, options: ${JSON.stringify(options)}`);
288
+
289
+ return await this.db.collection(this.table).createIndex(keys, options);
290
+ } catch (error) {
291
+ $.log.error(`[MongoDB] 创建索引失败: ${error.message}`);
292
+ throw error;
293
+ }
294
+ };
295
+
296
+ /**
297
+ * @description 创建TTL索引(数据自动过期)
298
+ * @param {Object} keys 索引键配置 {field: 1}
299
+ * @param {Number} expireAfterSeconds 过期时间(秒)
300
+ * @returns {Promise<Object>} 创建索引的结果
301
+ */
302
+ MongoDB.prototype.createTTLIndex = async function (keys, expireAfterSeconds) {
303
+ try {
304
+ if (!this.db || !this.table) {
305
+ throw new Error('数据库未连接或未指定表名');
306
+ }
307
+
308
+ const options = {
309
+ background: true,
310
+ expireAfterSeconds: expireAfterSeconds
311
+ };
312
+
313
+ $.log.info(`[MongoDB] 创建TTL索引: ${this.table}, keys: ${JSON.stringify(keys)}, 过期时间: ${expireAfterSeconds}秒`);
314
+
315
+ return await this.db.collection(this.table).createIndex(keys, options);
316
+ } catch (error) {
317
+ $.log.error(`[MongoDB] 创建TTL索引失败: ${error.message}`);
318
+ throw error;
319
+ }
320
+ };
321
+
322
+ /**
323
+ * @description 获取集合的所有索引
324
+ * @returns {Promise<Array>} 索引信息数组
325
+ */
326
+ MongoDB.prototype.getIndexes = async function () {
327
+ try {
328
+ if (!this.db || !this.table) {
329
+ throw new Error('数据库未连接或未指定表名');
330
+ }
331
+
332
+ $.log.info(`[MongoDB] 获取索引: ${this.table}`);
333
+ return await this.db.collection(this.table).indexes();
334
+ } catch (error) {
335
+ $.log.error(`[MongoDB] 获取索引失败: ${error.message}`);
336
+ return [];
337
+ }
338
+ };
339
+
340
+ /**
341
+ * @description 删除指定索引
342
+ * @param {String} indexName 索引名称
343
+ * @returns {Promise<Boolean>} 是否删除成功
344
+ */
345
+ MongoDB.prototype.dropIndex = async function (indexName) {
346
+ if (!this.conn || !this.db) {
347
+ throw new Error('数据库未连接');
348
+ }
349
+ if (!this.table) {
350
+ throw new Error('未指定表名');
351
+ }
352
+ if (!indexName) {
353
+ throw new Error('索引名称不能为空');
354
+ }
355
+ try {
356
+ $.log.info(`[MongoDB] 删除索引: ${this.table}, 索引名: ${indexName}`);
357
+ await this.db.collection(this.table).dropIndex(indexName);
358
+ return true;
359
+ } catch (error) {
360
+ $.log.error(`[MongoDB] 删除索引失败: ${error.message}`);
361
+ throw error;
362
+ }
363
+ };
364
+
365
+ /**
366
+ * @description 删除集合(表)
367
+ * @returns {Promise<Boolean>} 是否删除成功
368
+ */
369
+ MongoDB.prototype.dropTable = async function () {
370
+ if (!this.conn || !this.db) {
371
+ throw new Error('数据库未连接');
372
+ }
373
+ if (!this.table) {
374
+ throw new Error('未指定表名');
375
+ }
376
+ try {
377
+ $.log.info(`[MongoDB] 删除集合: ${this.table}`);
378
+ await this.db.collection(this.table).drop();
379
+ return true;
380
+ } catch (error) {
381
+ $.log.error(`[MongoDB] 删除集合失败: ${error.message}`);
382
+ throw error;
383
+ }
384
+ };
385
+
139
386
  /**
140
387
  * @description 增加一条缓存
141
388
  * @param {Object} obj 对象
142
389
  * @return {Promise|Object} 执行结果
143
390
  */
144
- MongoDB.prototype.addObj = function(obj) {
145
- return this.db.collection(this.table).insertOne(obj);
391
+ MongoDB.prototype.addObj = async function(obj) {
392
+ try {
393
+ // 触发前置事件
394
+ this.emit('beforeInsert', { table: this.table, data: obj });
395
+
396
+ // 执行插入操作
397
+ const result = await this.db.collection(this.table).insertOne(obj);
398
+
399
+ // 触发后置事件
400
+ this.emit('afterInsert', { table: this.table, data: obj, result });
401
+
402
+ return result;
403
+ } catch (error) {
404
+ // 触发错误事件
405
+ this.emit('insertError', { table: this.table, data: obj, error });
406
+ throw error;
407
+ }
146
408
  };
147
409
 
148
410
  /**
@@ -150,8 +412,23 @@ MongoDB.prototype.addObj = function(obj) {
150
412
  * @param {Array} list 对象数组
151
413
  * @return {Promise|Object} 执行结果
152
414
  */
153
- MongoDB.prototype.addList = function(list) {
154
- return this.db.collection(this.table).insertMany(list);
415
+ MongoDB.prototype.addList = async function(list) {
416
+ try {
417
+ // 触发前置事件
418
+ this.emit('beforeInsertMany', { table: this.table, data: list });
419
+
420
+ // 执行插入操作
421
+ const result = await this.db.collection(this.table).insertMany(list);
422
+
423
+ // 触发后置事件
424
+ this.emit('afterInsertMany', { table: this.table, data: list, result });
425
+
426
+ return result;
427
+ } catch (error) {
428
+ // 触发错误事件
429
+ this.emit('insertManyError', { table: this.table, data: list, error });
430
+ throw error;
431
+ }
155
432
  };
156
433
 
157
434
  /**
@@ -159,43 +436,185 @@ MongoDB.prototype.addList = function(list) {
159
436
  * @param {Object} query 查询条件对象
160
437
  * @return {Promise|Object} 执行结果
161
438
  */
162
- MongoDB.prototype.del = function(query) {
163
- return this.db.collection(this.table).remove(query);
439
+ MongoDB.prototype.del = async function(query) {
440
+ try {
441
+ // 触发前置事件
442
+ this.emit('beforeDelete', { table: this.table, query });
443
+
444
+ // 执行删除操作
445
+ const result = await this.db.collection(this.table).deleteMany(query);
446
+
447
+ // 触发后置事件
448
+ this.emit('afterDelete', { table: this.table, query, result });
449
+
450
+ return result;
451
+ } catch (error) {
452
+ // 触发错误事件
453
+ this.emit('deleteError', { table: this.table, query, error });
454
+ throw error;
455
+ }
164
456
  };
165
457
 
166
458
  /**
167
459
  * @description 修改缓存
168
460
  * @param {Object} query 查询条件对象
169
461
  * @param {Object} body 修改对象
462
+ * @param {Object} options 附加选项
170
463
  * @return {Promise|Object} 执行结果
171
464
  */
172
- MongoDB.prototype.set = function(query, body) {
173
- return this.db.collection(this.table).update(query, body);
465
+ MongoDB.prototype.set = async function(query, body, options = {}) {
466
+ try {
467
+ // 默认使用$set操作符进行部分更新
468
+ if (!body.$set && !body.$inc && !body.$push) {
469
+ body = { $set: body };
470
+ }
471
+ // 默认更新多条
472
+ const updateOptions = Object.assign({ multi: true }, options);
473
+
474
+ // 触发前置事件
475
+ this.emit('beforeUpdate', { table: this.table, query, update: body, options: updateOptions });
476
+
477
+ // 执行更新操作
478
+ const result = await this.db.collection(this.table).updateMany(query, body, updateOptions);
479
+
480
+ // 触发后置事件
481
+ this.emit('afterUpdate', { table: this.table, query, update: body, options: updateOptions, result });
482
+
483
+ return result;
484
+ } catch (error) {
485
+ // 触发错误事件
486
+ this.emit('updateError', { table: this.table, query, update: body, options, error });
487
+ throw error;
488
+ }
174
489
  };
175
490
 
176
491
  /**
177
492
  * @description 查询缓存
178
493
  * @param {Object} query 查询条件对象
179
- * @return {Promise|Array} 执行结果
494
+ * @param {Object} options 查询选项
495
+ * @return {Promise|Array} 查询结果数组
180
496
  */
181
- MongoDB.prototype.get = function(query) {
182
- if (this.page !== 0 && this.size !== 0) {
183
- return this.db.collection(this.table).find(query).limit(this.size).skip((this.page - 1) * this
184
- .size).toArray();
185
- } else {
186
- return this.db.collection(this.table).find(query).toArray();
497
+ MongoDB.prototype.find = async function (query, options = {}) {
498
+ try {
499
+ // 安全处理查询条件,避免注入
500
+ const safeQuery = this._sanitizeQuery(query);
501
+ const cursor = this.db.collection(this.table).find(safeQuery, options);
502
+ return await cursor.toArray();
503
+ } catch (error) {
504
+ $.log.error('[MongoDB] 查询失败:', error);
505
+ return [];
187
506
  }
188
507
  };
189
508
 
190
509
  /**
191
- * @module 导出MongoDB帮助类
510
+ * @description 查询单条数据
511
+ * @param {Object} query 查询条件对象
512
+ * @param {Object} options 查询选项
513
+ * @return {Promise<Object|null>} 查询结果
192
514
  */
193
- exports.MongoDB = MongoDB;
515
+ MongoDB.prototype.findOne = async function (query, options = {}) {
516
+ try {
517
+ const safeQuery = this._sanitizeQuery(query);
518
+ return await this.db.collection(this.table).findOne(safeQuery, options);
519
+ } catch (error) {
520
+ $.log.error('[MongoDB] 查询单条数据失败:', error);
521
+ return null;
522
+ }
523
+ };
524
+
525
+ /**
526
+ * @description 计算文档数量
527
+ * @param {Object} query 查询条件对象
528
+ * @return {Promise<Number>} 文档数量
529
+ */
530
+ MongoDB.prototype.count = async function (query = {}) {
531
+ try {
532
+ const safeQuery = this._sanitizeQuery(query);
533
+ return await this.db.collection(this.table).countDocuments(safeQuery);
534
+ } catch (error) {
535
+ $.log.error('[MongoDB] 计算文档数量失败:', error);
536
+ return 0;
537
+ }
538
+ };
539
+
540
+ /**
541
+ * @private
542
+ * @description 清理查询条件,防止注入攻击
543
+ * @param {Object} query 查询条件
544
+ * @return {Object} 安全的查询条件
545
+ */
546
+ MongoDB.prototype._sanitizeQuery = function (query) {
547
+ // 简单实现,可根据需要扩展更复杂的安全检查
548
+ const sanitized = {};
549
+
550
+ for (const [key, value] of Object.entries(query)) {
551
+ // 防止NoSQL注入,如 {$ne: null} 等操作符注入
552
+ if (key.startsWith('$') && typeof key === 'string' && !Array.isArray(value) && typeof value === 'object' && value !== null) {
553
+ $.log.warn('[MongoDB] 检测到可能的操作符注入尝试:', key);
554
+ continue;
555
+ }
556
+ sanitized[key] = value;
557
+ }
558
+
559
+ return sanitized;
560
+ };
561
+
562
+ /**
563
+ * @description 启动事务
564
+ * @return {Promise<Object>} 会话对象
565
+ */
566
+ MongoDB.prototype.startTransaction = async function () {
567
+ try {
568
+ const session = this.conn.startSession();
569
+ session.startTransaction();
570
+ return session;
571
+ } catch (error) {
572
+ $.log.error('[MongoDB] 启动事务失败:', error);
573
+ throw error;
574
+ }
575
+ };
576
+
577
+ /**
578
+ * @description 提交事务
579
+ * @param {Object} session 会话对象
580
+ * @return {Promise<void>}
581
+ */
582
+ MongoDB.prototype.commitTransaction = async function (session) {
583
+ try {
584
+ await session.commitTransaction();
585
+ await session.endSession();
586
+ } catch (error) {
587
+ $.log.error('[MongoDB] 提交事务失败:', error);
588
+ throw error;
589
+ }
590
+ };
591
+
592
+ /**
593
+ * @description 回滚事务
594
+ * @param {Object} session 会话对象
595
+ * @return {Promise<void>}
596
+ */
597
+ MongoDB.prototype.rollbackTransaction = async function (session) {
598
+ try {
599
+ await session.abortTransaction();
600
+ await session.endSession();
601
+ } catch (error) {
602
+ $.log.error('[MongoDB] 回滚事务失败:', error);
603
+ throw error;
604
+ }
605
+ };
194
606
 
607
+ /**
608
+ * 导出MongoDB类
609
+ */
610
+ exports.MongoDB = MongoDB;
195
611
 
196
612
  /**
197
- * @description mongoDB连接池
613
+ * 确保连接池对象存在
198
614
  */
615
+ if (!$.pool) {
616
+ $.pool = {};
617
+ }
199
618
  if (!$.pool.mongoDB) {
200
619
  $.pool.mongoDB = {};
201
620
  }
@@ -204,11 +623,11 @@ if (!$.pool.mongoDB) {
204
623
  * @description MongoDB管理器,用于创建缓存
205
624
  * @param {String} scope 作用域
206
625
  * @param {String} dir 当前路径
207
- * @return {Object} 返回一个缓存类
626
+ * @return {Object} 返回一个MongoDB类实例
208
627
  */
209
628
  function mongoDB_admin(scope, dir) {
210
629
  if (!scope) {
211
- scope = $.val.scope
630
+ scope = ($.val && $.val.scope) || 'default';
212
631
  }
213
632
  var obj = $.pool.mongoDB[scope];
214
633
  if (!obj) {
@@ -221,4 +640,4 @@ function mongoDB_admin(scope, dir) {
221
640
  /**
222
641
  * @module 导出MongoDB管理器
223
642
  */
224
- exports.mongoDB_admin = mongoDB_admin;
643
+ exports.mongoDB_admin = mongoDB_admin;