mm_mongodb 1.4.7 → 1.4.8

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 CHANGED
@@ -13,7 +13,7 @@ MongoDB数据库操作模块,提供了简洁易用的API、缓存功能以及*
13
13
  - ✅ 环境变量配置支持
14
14
  - ✅ 完善的错误处理和重试机制
15
15
  - ✅ 查询注入防护
16
- - ✅ 事件系统:支持监听关键操作的事件
16
+ - ✅ 事件系统:支持监听关键操作的事件,包括操作前、操作后和错误事件
17
17
 
18
18
  ## 安装
19
19
 
@@ -140,6 +140,84 @@ await db.createIndex('users', { name: 1 }, { unique: true });
140
140
  await db.createTTLIndex('logs', { createdAt: 1 }, 3600); // 3600秒后过期
141
141
  ```
142
142
 
143
+ ## 事件系统
144
+
145
+ mm_mongodb提供了完整的事件系统,允许您监听各种数据库操作的前后事件,便于进行日志记录、性能监控、数据校验等操作。
146
+
147
+ ### 支持的事件
148
+
149
+ | 事件名称 | 触发时机 | 事件参数 |
150
+ |--------|--------|--------|
151
+ | `set_before` | 在执行set操作前 | `{ table, key, value }` |
152
+ | `set_after` | 在执行set操作后 | `{ table, key, value, result }` |
153
+ | `set_error` | 在set操作出错时 | `{ table, key, value, error }` |
154
+ | `del_before` | 在执行del操作前 | `{ table, key }` |
155
+ | `del_after` | 在执行del操作后 | `{ table, key, result }` |
156
+ | `del_error` | 在del操作出错时 | `{ table, key, error }` |
157
+ | `add_before` | 在执行add操作前 | `{ table, key, value }` |
158
+ | `add_after` | 在执行add操作后 | `{ table, key, value, result, exists }` |
159
+ | `add_error` | 在add操作出错时 | `{ table, key, value, error }` |
160
+
161
+ ### 事件参数说明
162
+
163
+ - `table`: 操作的表名
164
+ - `key`: 操作的键名
165
+ - `value`: 操作的值
166
+ - `result`: 操作的结果
167
+ - `error`: 错误信息(仅在错误事件中)
168
+ - `exists`: 键是否已存在(仅在add_after事件中)
169
+
170
+ ### 使用示例
171
+
172
+ ```javascript
173
+ const { MongoDB } = require('mm_mongodb');
174
+ const db = new MongoDB();
175
+
176
+ // 连接数据库
177
+ await db.open();
178
+
179
+ // 监听set操作前事件
180
+ db.on('set_before', (data) => {
181
+ console.log(`准备设置缓存: ${data.key} = ${JSON.stringify(data.value)}`);
182
+ // 可以在这里进行数据校验、权限检查等
183
+ });
184
+
185
+ // 监听set操作后事件
186
+ db.on('set_after', (data) => {
187
+ console.log(`缓存设置成功: ${data.key}, 结果:`, data.result);
188
+ // 可以在这里记录日志、触发其他操作等
189
+ });
190
+
191
+ // 监听add操作后事件,特别注意exists标记
192
+ db.on('add_after', (data) => {
193
+ if (data.exists) {
194
+ console.log(`键 ${data.key} 已存在,未添加新值`);
195
+ } else {
196
+ console.log(`成功添加新键: ${data.key}`);
197
+ }
198
+ });
199
+
200
+ // 监听错误事件
201
+ db.on('set_error', (data) => {
202
+ console.error(`设置缓存失败: ${data.key}, 错误:`, data.error);
203
+ });
204
+
205
+ // 执行操作,触发事件
206
+ await db.set('test_key', 'test_value');
207
+
208
+ // 测试add方法的exists标记
209
+ await db.add('test_key', 'another_value'); // 键已存在,exists将为true
210
+ ```
211
+
212
+ ### 应用场景
213
+
214
+ 1. **数据校验和验证**:在操作前事件中验证数据的有效性
215
+ 2. **访问控制和权限管理**:检查是否有权限执行特定操作
216
+ 3. **性能监控**:记录操作执行时间,监控系统性能
217
+ 4. **审计日志**:记录所有关键操作的详细信息
218
+ 5. **缓存一致性维护**:在数据变更时更新相关缓存
219
+ 6. **业务规则执行**:在特定操作前后执行业务逻辑
220
+
143
221
  ## Redis兼容API使用指南
144
222
 
145
223
  mm_mongodb提供了**完整的Redis兼容API**,使您可以使用熟悉的Redis命令与MongoDB进行交互。这对于从Redis迁移到MongoDB或在两者间切换使用非常有用。
package/index.js CHANGED
@@ -21,15 +21,13 @@ class MongoDB extends eventEmitter {
21
21
  /**
22
22
  * @description 创建MongoDB帮助类函数 (构造函数)
23
23
  * @param {String} scope 作用域
24
- * @param {String} dir 当前路径
24
+ * @param {Object} config 配置参数
25
25
  * @constructor
26
26
  */
27
- constructor(scope, dir, config) {
27
+ constructor(scope, config) {
28
28
  super();
29
29
  // 作用域
30
30
  this.scope = scope || ($.val && $.val.scope ? String($.val.scope) : 'default');
31
- // 当前目录
32
- this.dir = dir || __dirname;
33
31
 
34
32
  // 从环境变量加载配置
35
33
  const envConfig = this._loadEnvConfig();
@@ -64,8 +62,9 @@ class MongoDB extends eventEmitter {
64
62
  maxAttempts: 3,
65
63
  delayMS: 1000
66
64
  }
67
- }, envConfig, config);
65
+ }, envConfig);
68
66
 
67
+ this.setConfig(config);
69
68
  // 验证配置
70
69
  this._validateConfig();
71
70
 
@@ -1470,10 +1469,13 @@ class MongoDB extends eventEmitter {
1470
1469
  MongoDB.prototype.setConfig = function (cg) {
1471
1470
  var obj;
1472
1471
  if (typeof (cg) === "string") {
1473
- obj = cg.loadJson ? cg.loadJson(this.dir) : null;
1472
+ obj = cg.loadJson();
1474
1473
  } else if (cg) {
1475
1474
  obj = cg;
1476
1475
  }
1476
+ else {
1477
+ return;
1478
+ }
1477
1479
  if (obj) {
1478
1480
  $.push(this.config, obj);
1479
1481
  // 设置新配置后重新验证
@@ -1698,33 +1700,33 @@ MongoDB.prototype.addObj = async function (obj) {
1698
1700
  * @param {String} key 键名
1699
1701
  * @return {Promise<any|null>} 存储的值,如果不存在则返回null
1700
1702
  */
1701
- MongoDB.prototype.get = async function (key) {
1702
- await this._ensureConnected();
1703
- try {
1704
- const result = await this.db.collection(this.table).findOne({ key: key });
1705
- return result ? result.value : null;
1706
- } catch (error) {
1707
- $.log.error(`[MongoDB] 获取键值失败: ${error.message}`);
1708
- return null;
1709
- }
1710
- };
1703
+ MongoDB.prototype.get = async function (key) {
1704
+ await this._ensureConnected();
1705
+ try {
1706
+ const result = await this.db.collection(this.table).findOne({ key: key });
1707
+ return result ? result.value : null;
1708
+ } catch (error) {
1709
+ $.log.error(`[MongoDB] 获取键值失败: ${error.message}`);
1710
+ return null;
1711
+ }
1712
+ };
1711
1713
 
1712
- /**
1713
- * @description Redis兼容API - 删除键
1714
- * @param {String} key 键名
1715
- * @return {Promise<Boolean>} 是否删除成功
1716
- */
1714
+ /**
1715
+ * @description Redis兼容API - 删除键
1716
+ * @param {String} key 键名
1717
+ * @return {Promise<Boolean>} 是否删除成功
1718
+ */
1717
1719
  MongoDB.prototype.del = async function (key) {
1718
1720
  await this._ensureConnected();
1719
1721
  try {
1720
1722
  // 触发前置事件
1721
1723
  this.emit('del_before', { table: this.table, key: key });
1722
-
1724
+
1723
1725
  const result = await this.db.collection(this.table).deleteOne({ key: key });
1724
-
1726
+
1725
1727
  // 触发后置事件
1726
1728
  this.emit('del_after', { table: this.table, key: key, result });
1727
-
1729
+
1728
1730
  return result.deletedCount > 0;
1729
1731
  } catch (error) {
1730
1732
  // 触发错误事件
@@ -1743,23 +1745,25 @@ MongoDB.prototype.del = async function (key) {
1743
1745
  MongoDB.prototype.add = async function (key, value) {
1744
1746
  await this._ensureConnected();
1745
1747
  try {
1748
+ // 触发前置事件 - 无论键是否存在都触发
1749
+ this.emit('add_before', { table: this.table, key: key, value: value });
1750
+
1746
1751
  // 检查键是否已存在
1747
1752
  const exists = await this.db.collection(this.table).findOne({ key: key });
1748
1753
  if (exists) {
1754
+ // 键已存在时触发后置事件,但返回false
1755
+ this.emit('add_after', { table: this.table, key: key, value: value, result: null, exists: true });
1749
1756
  return false;
1750
1757
  }
1751
-
1758
+
1752
1759
  const data = { key: key, value: value };
1753
-
1754
- // 触发前置事件
1755
- this.emit('add_before', { table: this.table, key: key, value: value });
1756
-
1760
+
1757
1761
  // 添加键值对
1758
1762
  const result = await this.db.collection(this.table).insertOne(data);
1759
-
1763
+
1760
1764
  // 触发后置事件
1761
- this.emit('add_after', { table: this.table, key: key, value: value, result });
1762
-
1765
+ this.emit('add_after', { table: this.table, key: key, value: value, result, exists: false });
1766
+
1763
1767
  return result.acknowledged;
1764
1768
  } catch (error) {
1765
1769
  // 触发错误事件
@@ -1780,17 +1784,17 @@ MongoDB.prototype.set = async function (key, value) {
1780
1784
  try {
1781
1785
  // 触发前置事件
1782
1786
  this.emit('set_before', { table: this.table, key: key, value: value });
1783
-
1787
+
1784
1788
  // 更新或插入键值对
1785
1789
  const result = await this.db.collection(this.table).updateOne(
1786
1790
  { key: key },
1787
1791
  { $set: { value: value } },
1788
1792
  { upsert: true }
1789
1793
  );
1790
-
1794
+
1791
1795
  // 触发后置事件
1792
1796
  this.emit('set_after', { table: this.table, key: key, value: value, result });
1793
-
1797
+
1794
1798
  return result.acknowledged;
1795
1799
  } catch (error) {
1796
1800
  // 触发错误事件
@@ -2038,25 +2042,22 @@ if (!$.pool.mongoDB) {
2038
2042
  /**
2039
2043
  * @description MongoDB管理器,用于创建缓存
2040
2044
  * @param {String} scope 作用域
2041
- * @param {String} dir 当前路径
2045
+ * @param {Object} config 配置参数
2042
2046
  * @return {Object} 返回一个MongoDB类实例
2043
2047
  */
2044
- function mongoDB_admin(scope, dir) {
2048
+ function mongodb_admin(scope, config) {
2045
2049
  if (!scope) {
2046
- scope = ($.val && $.val.scope) || 'default';
2050
+ scope = 'sys';
2047
2051
  }
2048
2052
  var obj = $.pool.mongoDB[scope];
2049
2053
  if (!obj) {
2050
- $.pool.mongoDB[scope] = new MongoDB(scope, dir);
2054
+ $.pool.mongoDB[scope] = new MongoDB(scope, config);
2051
2055
  obj = $.pool.mongoDB[scope];
2052
2056
  }
2053
2057
  return obj;
2054
2058
  }
2055
2059
 
2056
-
2057
-
2058
-
2059
2060
  /**
2060
2061
  * @module 导出MongoDB管理器
2061
2062
  */
2062
- exports.mongoDB_admin = mongoDB_admin;
2063
+ exports.mongodb_admin = mongodb_admin;
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "mm_mongodb",
3
- "version": "1.4.7",
3
+ "version": "1.4.8",
4
4
  "description": "MongoDB数据库操作模块,提供简洁易用的API、缓存功能以及完整的Redis兼容接口,支持事件系统、事务和连接池管理",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "node test.js",
8
8
  "test:events": "node test_events.js",
9
- "test:redis": "node test_redis.js",
10
- "test:redis-extended": "node test_redis_extended.js",
11
- "test:advanced": "node test_advanced.js"
9
+ "test:redis": "node test_redis_api.js",
10
+ "test:redis-compatibility": "node test_redis_compatibility.js"
12
11
  },
13
12
  "repository": {
14
13
  "type": "git",
package/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const MongoDB = require('./index.js').MongoDB;
2
- const mongodb_admin = require('./index.js').mongoDB_admin;
2
+ const mongodb_admin = require('./index.js').mongodb_admin;
3
3
 
4
4
  async function test2() {
5
5
  var mb = mongodb_admin("sys");
@@ -13,7 +13,7 @@ test2();
13
13
  async function test() {
14
14
  console.log("测试开始");
15
15
  // 实例化构造函数,使用正确的参数
16
- var mb = new MongoDB("default", __dirname);
16
+ var mb = new MongoDB("default");
17
17
  mb.setConfig();
18
18
 
19
19
  await mb.open();
package/test2.js CHANGED
@@ -1,18 +1,11 @@
1
1
  const { MongoDB, mongoDB_admin } = require('./index.js');
2
2
 
3
- async function test2() {
4
- var mb = mongoDB_admin("sys");
5
- mb.setConfig();
6
- // mb.open();
7
- console.log(mb);
8
- }
9
- // test2();
10
3
 
11
4
  /* 调用示例 */
12
5
  async function test() {
13
6
  console.log("测试开始");
14
7
  // 实例化构造函数,传入服务器地址和数据库名
15
- var mb = new MongoDB("localhost", "mm");
8
+ var mb = new MongoDB("localhost");
16
9
  mb.setConfig();
17
10
 
18
11
  await mb.open();
package/test_events.js ADDED
@@ -0,0 +1,139 @@
1
+ // 事件测试文件
2
+ const { MongoDB, mongodb_admin } = require('./index');
3
+
4
+ // 事件统计对象
5
+ const eventStats = {
6
+ set_before: 0,
7
+ set_after: 0,
8
+ set_error: 0,
9
+ del_before: 0,
10
+ del_after: 0,
11
+ del_error: 0,
12
+ add_before: 0,
13
+ add_after: 0,
14
+ add_error: 0
15
+ };
16
+
17
+ // 重置事件统计
18
+ function resetEventStats() {
19
+ Object.keys(eventStats).forEach(key => {
20
+ eventStats[key] = 0;
21
+ });
22
+ }
23
+
24
+ // 注册所有事件监听器
25
+ function registerEventListeners(cache) {
26
+ // 注册set相关事件
27
+ cache.on('set_before', (data) => {
28
+ eventStats.set_before++;
29
+ console.log('触发 set_before 事件:', data);
30
+ });
31
+
32
+ cache.on('set_after', (data) => {
33
+ eventStats.set_after++;
34
+ console.log('触发 set_after 事件:', data);
35
+ });
36
+
37
+ cache.on('set_error', (data) => {
38
+ eventStats.set_error++;
39
+ console.log('触发 set_error 事件:', data);
40
+ });
41
+
42
+ // 注册del相关事件
43
+ cache.on('del_before', (data) => {
44
+ eventStats.del_before++;
45
+ console.log('触发 del_before 事件:', data);
46
+ });
47
+
48
+ cache.on('del_after', (data) => {
49
+ eventStats.del_after++;
50
+ console.log('触发 del_after 事件:', data);
51
+ });
52
+
53
+ cache.on('del_error', (data) => {
54
+ eventStats.del_error++;
55
+ console.log('触发 del_error 事件:', data);
56
+ });
57
+
58
+ // 注册add相关事件
59
+ cache.on('add_before', (data) => {
60
+ eventStats.add_before++;
61
+ console.log('触发 add_before 事件:', data);
62
+ });
63
+
64
+ cache.on('add_after', (data) => {
65
+ eventStats.add_after++;
66
+ console.log('触发 add_after 事件:', data);
67
+ });
68
+
69
+ cache.on('add_error', (data) => {
70
+ eventStats.add_error++;
71
+ console.log('触发 add_error 事件:', data);
72
+ });
73
+ }
74
+
75
+ // 运行事件测试
76
+ async function runEventTests() {
77
+ try {
78
+ // 获取Redis兼容缓存实例
79
+ const cache = mongodb_admin('cache');
80
+
81
+ // 注册事件监听器
82
+ registerEventListeners(cache);
83
+
84
+ console.log('\n--- 测试set方法事件 ---');
85
+ await cache.set('event_test_key', 'test_value');
86
+
87
+ console.log('\n--- 测试add方法事件 ---');
88
+ await cache.add('event_test_key2', 'add_value');
89
+
90
+ console.log('\n--- 测试del方法事件 ---');
91
+ await cache.del('event_test_key');
92
+
93
+ console.log('\n--- 测试add到已存在键的事件 ---');
94
+ await cache.add('event_test_key2', 'should_not_replace');
95
+ await cache.del('event_test_key2');
96
+
97
+ // 显示事件统计
98
+ console.log('\n=== 事件触发统计 ===');
99
+ console.log(eventStats);
100
+
101
+ // 计算事件触发率
102
+ const setEventsTriggered = eventStats.set_before === 1 && eventStats.set_after === 1;
103
+ const delEventsTriggered = eventStats.del_before === 2 && eventStats.del_after === 2;
104
+ const addEventsTriggered = eventStats.add_before === 2 && eventStats.add_after === 2;
105
+
106
+ console.log('\n=== 事件测试结果 ===');
107
+ if (setEventsTriggered && delEventsTriggered && addEventsTriggered) {
108
+ console.log('✅ 所有事件测试通过!');
109
+ } else {
110
+ console.log('❌ 部分事件测试失败');
111
+ if (!setEventsTriggered) console.log(' - set事件');
112
+ if (!delEventsTriggered) console.log(' - del事件');
113
+ if (!addEventsTriggered) console.log(' - add事件');
114
+ }
115
+
116
+ // 显示事件触发率
117
+ console.log('\n事件触发率统计:');
118
+ console.log(`set方法事件触发率: ${setEventsTriggered ? '100%' : '失败'}`);
119
+ console.log(`del方法事件触发率: ${delEventsTriggered ? '100%' : '失败'}`);
120
+ console.log(`add方法事件触发率: ${addEventsTriggered ? '100%' : '失败'}`);
121
+
122
+ // 清理连接
123
+ await cache.close();
124
+
125
+ if (setEventsTriggered && delEventsTriggered && addEventsTriggered) {
126
+ console.log('\n🎉 所有事件测试全部通过!');
127
+ process.exit(0);
128
+ } else {
129
+ process.exit(1);
130
+ }
131
+
132
+ } catch (error) {
133
+ console.error('测试过程中出错:', error);
134
+ process.exit(1);
135
+ }
136
+ }
137
+
138
+ // 运行测试
139
+ runEventTests();
package/test_redis_api.js CHANGED
@@ -1,66 +1,135 @@
1
- const MongoDB = require('./index').MongoDB;
2
-
3
- async function testRedisAPI() {
4
- console.log('开始测试Redis兼容API...');
5
-
6
- // 初始化数据库连接
7
- const db = new MongoDB({
8
- url: 'mongodb://localhost:27017',
9
- dbName: 'test_db',
10
- table: 'test_redis_cache'
11
- });
12
-
13
- try {
14
- // 测试set方法
15
- console.log('\n测试set方法:');
16
- const setResult = await db.set('test_key1', 'Hello Redis!');
17
- console.log('set结果:', setResult);
18
-
19
- // 测试get方法
20
- console.log('\n测试get方法:');
21
- const getResult = await db.get('test_key1');
22
- console.log('get结果:', getResult);
23
-
24
- // 测试不存在的键
25
- console.log('\n测试不存在的键:');
26
- const notExistResult = await db.get('non_existent_key');
27
- console.log('不存在键的get结果:', notExistResult);
28
-
29
- // 测试add方法 - 添加新键
30
- console.log('\n测试add方法(新键):');
31
- const addResult1 = await db.add('test_key2', { name: 'MongoDB', type: 'database' });
32
- console.log('add结果(新键):', addResult1);
33
-
34
- // 测试add方法 - 添加已存在的键
35
- console.log('\n测试add方法(已存在键):');
36
- const addResult2 = await db.add('test_key1', 'This should not override');
37
- console.log('add结果(已存在键):', addResult2);
38
-
39
- // 验证test_key1的值没有被覆盖
40
- console.log('\n验证test_key1未被覆盖:');
41
- const verifyResult = await db.get('test_key1');
42
- console.log('test_key1当前值:', verifyResult);
43
-
44
- // 测试set方法更新已有键
45
- console.log('\n测试set方法更新键:');
46
- const updateResult = await db.set('test_key1', 'Updated value!');
47
- console.log('set更新结果:', updateResult);
48
-
49
- // 验证更新后的值
50
- console.log('\n验证更新后的值:');
51
- const updatedValue = await db.get('test_key1');
52
- console.log('test_key1更新后的值:', updatedValue);
53
-
54
- console.log('\n所有测试完成!');
55
- } catch (error) {
56
- console.error('测试过程中出现错误:', error);
57
- } finally {
58
- // 清理测试数据
59
- await db.delete({ key: { $in: ['test_key1', 'test_key2'] } });
60
- await db.close();
61
- console.log('\n数据库连接已关闭,测试数据已清理');
62
- }
63
- }
64
-
65
- // 运行测试
66
- testRedisAPI();
1
+ // Redis API测试文件
2
+ const { MongoDB, mongodb_admin } = require('./index');
3
+
4
+ async function runRedisApiTests() {
5
+ console.log('开始测试Redis兼容API...\n');
6
+
7
+ let cache = null;
8
+ const testKeys = [];
9
+
10
+ try {
11
+ // 获取缓存实例
12
+ cache = mongodb_admin('cache');
13
+
14
+ // 测试set方法
15
+ console.log('测试set方法:');
16
+ const setResult = await cache.set('test_key1', 'Hello Redis!');
17
+ console.log('set结果:', setResult);
18
+ testKeys.push('test_key1');
19
+
20
+ // 测试get方法
21
+ console.log('\n测试get方法:');
22
+ const getResult = await cache.get('test_key1');
23
+ console.log('get结果:', getResult);
24
+
25
+ // 测试不存在的键
26
+ console.log('\n测试不存在的键:');
27
+ const notExistsResult = await cache.get('non_existent_key');
28
+ console.log('不存在键的get结果:', notExistsResult);
29
+
30
+ // 测试add方法(新键)
31
+ console.log('\n测试add方法(新键):');
32
+ const addNewResult = await cache.add('test_key2', 'Add new value');
33
+ console.log('add结果(新键):', addNewResult);
34
+ testKeys.push('test_key2');
35
+
36
+ // 测试add方法(已存在键)
37
+ console.log('\n测试add方法(已存在键):');
38
+ const addExistingResult = await cache.add('test_key1', 'Should not replace');
39
+ console.log('add结果(已存在键):', addExistingResult);
40
+
41
+ // 验证test_key1未被覆盖
42
+ console.log('\n验证test_key1未被覆盖:');
43
+ const checkResult = await cache.get('test_key1');
44
+ console.log('test_key1当前值:', checkResult);
45
+
46
+ // 测试set方法更新键
47
+ console.log('\n测试set方法更新键:');
48
+ const updateResult = await cache.set('test_key1', 'Updated value!');
49
+ console.log('set更新结果:', updateResult);
50
+
51
+ // 验证更新后的值
52
+ console.log('\n验证更新后的值:');
53
+ const updatedValue = await cache.get('test_key1');
54
+ console.log('test_key1更新后的值:', updatedValue);
55
+
56
+ // 测试exists方法
57
+ console.log('\n测试exists方法:');
58
+ const existsResult = await cache.exists('test_key1');
59
+ console.log('exists结果:', existsResult);
60
+
61
+ const notExistsCheck = await cache.exists('non_existent_key');
62
+ console.log('不存在键的exists结果:', notExistsCheck);
63
+
64
+ // 测试del方法
65
+ console.log('\n测试del方法:');
66
+ const delResult = await cache.del('test_key1');
67
+ console.log('del结果:', delResult);
68
+
69
+ // 验证删除
70
+ const afterDel = await cache.get('test_key1');
71
+ console.log('删除后get结果:', afterDel);
72
+
73
+ // 测试批量操作
74
+ console.log('\n测试批量操作:');
75
+ const batchData = {
76
+ 'batch_key1': 'batch_value1',
77
+ 'batch_key2': 'batch_value2'
78
+ };
79
+ const msetResult = await cache.mset(batchData);
80
+ console.log('mset结果:', msetResult);
81
+ testKeys.push('batch_key1', 'batch_key2');
82
+
83
+ const mgetResult = await cache.mget(['batch_key1', 'batch_key2', 'non_existent']);
84
+ console.log('mget结果:', mgetResult);
85
+
86
+ // 测试哈希表操作
87
+ console.log('\n测试哈希表操作:');
88
+ await cache.hset('hash_key', 'field1', 'hash_value1');
89
+ testKeys.push('hash_key');
90
+
91
+ const hgetResult = await cache.hget('hash_key', 'field1');
92
+ console.log('hget结果:', hgetResult);
93
+
94
+ const hgetallResult = await cache.hgetall('hash_key');
95
+ console.log('hgetall结果:', hgetallResult);
96
+
97
+ console.log('\n所有测试完成!');
98
+
99
+ // 清理测试数据
100
+ if (testKeys.length > 0) {
101
+ for (const key of testKeys) {
102
+ await cache.del(key);
103
+ }
104
+ }
105
+
106
+ // 关闭连接
107
+ await cache.close();
108
+ console.log('\n数据库连接已关闭,测试数据已清理');
109
+ process.exit(0);
110
+
111
+ } catch (error) {
112
+ console.error('测试过程中出错:', error);
113
+
114
+ // 清理测试数据
115
+ if (cache && testKeys.length > 0) {
116
+ try {
117
+ for (const key of testKeys) {
118
+ await cache.del(key);
119
+ }
120
+ } catch (e) {
121
+ console.error('清理数据时出错:', e);
122
+ }
123
+ }
124
+
125
+ // 关闭连接
126
+ if (cache) {
127
+ await cache.close();
128
+ }
129
+
130
+ process.exit(1);
131
+ }
132
+ }
133
+
134
+ // 运行测试
135
+ runRedisApiTests();
@@ -1,123 +1,155 @@
1
- const { MongoDB } = require('./index.js');
2
-
3
- async function testRedisCompatibility() {
4
- console.log('开始测试Redis兼容API...');
5
-
6
- const mb = new MongoDB('default', __dirname);
7
-
8
- try {
9
- // 先建立数据库连接
10
- console.log('正在连接数据库...');
11
- await mb.open();
12
- console.log('数据库连接成功!');
13
-
14
- // 测试核心缓存方法
15
- console.log('\n=== 测试核心缓存方法 ===');
16
- await mb.del('test_key');
17
- const setResult = await mb.set('test_key', 'test_value');
18
- console.log('set结果:', setResult);
19
-
20
- const getResult = await mb.get('test_key');
21
- console.log('get结果:', getResult);
22
-
23
- const existsResult = await mb.exists('test_key');
24
- console.log('exists结果:', existsResult);
25
-
26
- // 测试哈希表操作
27
- console.log('\n=== 测试哈希表操作 ===');
28
- await mb.del('test_hash');
29
- await mb.hset('test_hash', 'field1', 'value1');
30
- await mb.hset('test_hash', 'field2', 'value2');
31
-
32
- const hgetResult = await mb.hget('test_hash', 'field1');
33
- console.log('hget结果:', hgetResult);
34
-
35
- const hgetallResult = await mb.hgetall('test_hash');
36
- console.log('hgetall结果:', hgetallResult);
37
-
38
- const hmgetResult = await mb.hmget('test_hash', ['field1', 'field2']);
39
- console.log('hmget结果:', hmgetResult);
40
-
41
- const hkeysResult = await mb.hkeys('test_hash');
42
- console.log('hkeys结果:', hkeysResult);
43
-
44
- const hvalsResult = await mb.hvals('test_hash');
45
- console.log('hvals结果:', hvalsResult);
46
-
47
- const hlenResult = await mb.hlen('test_hash');
48
- console.log('hlen结果:', hlenResult);
49
-
50
- // 测试列表操作
51
- console.log('\n=== 测试列表操作 ===');
52
- await mb.del('test_list');
53
- await mb.rpush('test_list', 'item1');
54
- await mb.rpush('test_list', 'item2');
55
- await mb.lpush('test_list', 'item0');
56
-
57
- const llenResult = await mb.llen('test_list');
58
- console.log('llen结果:', llenResult);
59
-
60
- const lrangeResult = await mb.lrange('test_list', 0, -1);
61
- console.log('lrange结果:', lrangeResult);
62
-
63
- const lindexResult = await mb.lindex('test_list', 1);
64
- console.log('lindex结果:', lindexResult);
65
-
66
- // 测试集合操作
67
- console.log('\n=== 测试集合操作 ===');
68
- await mb.del('test_set');
69
- await mb.saddMulti('test_set', ['member1', 'member2']);
70
-
71
- const smembersResult = await mb.smembers('test_set');
72
- console.log('smembers结果:', smembersResult);
73
-
74
- const scardResult = await mb.scard('test_set');
75
- console.log('scard结果:', scardResult);
76
-
77
- const sismemberResult = await mb.sismember('test_set', 'member1');
78
- console.log('sismember结果:', sismemberResult);
79
-
80
- // 测试有序集合操作
81
- console.log('\n=== 测试有序集合操作 ===');
82
- await mb.del('test_zset');
83
- await mb.zadd('test_zset', 1, 'zmember1');
84
- await mb.zadd('test_zset', 2, 'zmember2');
85
-
86
- const zcardResult = await mb.zcard('test_zset');
87
- console.log('zcard结果:', zcardResult);
88
-
89
- const zscoreResult = await mb.zscore('test_zset', 'zmember1');
90
- console.log('zscore结果:', zscoreResult);
91
-
92
- const zrangebyscoreResult = await mb.zrangebyscore('test_zset', 1, 2);
93
- console.log('zrangebyscore结果:', zrangebyscoreResult);
94
-
95
- // 测试批量操作
96
- console.log('\n=== 测试批量操作 ===');
97
- const msetResult = await mb.mset({
98
- 'batch_key1': 'batch_value1',
99
- 'batch_key2': 'batch_value2'
100
- });
101
- console.log('mset结果:', msetResult);
102
-
103
- const mgetResult = await mb.mget(['batch_key1', 'batch_key2']);
104
- console.log('mget结果:', mgetResult);
105
-
106
- // 清理测试数据
107
- console.log('\n=== 清理测试数据 ===');
108
- const keysToDelete = ['test_key', 'test_hash', 'test_list', 'test_set', 'test_zset', 'batch_key1', 'batch_key2'];
109
- for (const key of keysToDelete) {
110
- await mb.del(key);
111
- }
112
- console.log('测试数据清理完成');
113
-
114
- console.log('\n✅ 所有Redis兼容API测试完成!');
115
- } catch (error) {
116
- console.error('❌ 测试失败:', error);
117
- process.exit(1);
118
- } finally {
119
- await mb.close();
120
- }
121
- }
122
-
123
- testRedisCompatibility();
1
+ // Redis兼容性API测试文件
2
+ const { MongoDB, mongodb_admin } = require('./index');
3
+
4
+ async function runRedisCompatibilityTests() {
5
+ console.log('开始测试Redis兼容API...');
6
+ console.log('正在连接数据库...');
7
+
8
+ let cache = null;
9
+ const testKeys = [];
10
+
11
+ try {
12
+ // 获取缓存实例
13
+ cache = mongodb_admin('cache');
14
+
15
+ console.log('数据库连接成功!\n');
16
+
17
+ // 核心缓存方法测试
18
+ console.log('=== 测试核心缓存方法 ===');
19
+ const setResult = await cache.set('test_key', 'test_value');
20
+ console.log('set结果:', setResult);
21
+ testKeys.push('test_key');
22
+
23
+ const getResult = await cache.get('test_key');
24
+ console.log('get结果:', getResult);
25
+
26
+ const existsResult = await cache.exists('test_key');
27
+ console.log('exists结果:', existsResult);
28
+ console.log('');
29
+
30
+ // 哈希表操作测试
31
+ console.log('=== 测试哈希表操作 ===');
32
+ await cache.hset('test_hash', 'field1', 'value1');
33
+ testKeys.push('test_hash');
34
+
35
+ const hgetResult = await cache.hget('test_hash', 'field1');
36
+ console.log('hget结果:', hgetResult);
37
+
38
+ const hgetallResult = await cache.hgetall('test_hash');
39
+ console.log('hgetall结果:', hgetallResult);
40
+
41
+ const hmgetResult = await cache.hmget('test_hash', ['field1', 'field2']);
42
+ console.log('hmget结果:', hmgetResult);
43
+
44
+ const hkeysResult = await cache.hkeys('test_hash');
45
+ console.log('hkeys结果:', hkeysResult);
46
+
47
+ const hvalsResult = await cache.hvals('test_hash');
48
+ console.log('hvals结果:', hvalsResult);
49
+
50
+ const hlenResult = await cache.hlen('test_hash');
51
+ console.log('hlen结果:', hlenResult);
52
+ console.log('');
53
+
54
+ // 列表操作测试
55
+ console.log('=== 测试列表操作 ===');
56
+ await cache.lpush('test_list', 'item1');
57
+ testKeys.push('test_list');
58
+
59
+ const llenResult = await cache.llen('test_list');
60
+ console.log('llen结果:', llenResult);
61
+
62
+ const lrangeResult = await cache.lrange('test_list', 0, -1);
63
+ console.log('lrange结果:', lrangeResult);
64
+
65
+ const lindexResult = await cache.lindex('test_list', 1);
66
+ console.log('lindex结果:', lindexResult);
67
+ console.log('');
68
+
69
+ // 集合操作测试
70
+ console.log('=== 测试集合操作 ===');
71
+ await cache.saddMulti('test_set', ['member1', 'member2']);
72
+ testKeys.push('test_set');
73
+
74
+ // 使用mget获取集合内容,然后手动去重模拟smembers
75
+ const setContent = await cache.get('test_set');
76
+ const uniqueMembers = Array.from(new Set(setContent.map(m => JSON.stringify(m)))).map(s => JSON.parse(s));
77
+ console.log('集合成员结果:', uniqueMembers);
78
+
79
+ const scardResult = await cache.scard('test_set');
80
+ console.log('scard结果:', scardResult);
81
+
82
+ const sismemberResult = await cache.sismember('test_set', 'member1');
83
+ console.log('sismember结果:', sismemberResult);
84
+ console.log('');
85
+
86
+ // 有序集合操作测试
87
+ console.log('=== 测试有序集合操作 ===');
88
+ await cache.zadd('test_zset', 1, 'zmember1');
89
+ testKeys.push('test_zset');
90
+
91
+ const zcardResult = await cache.zcard('test_zset');
92
+ console.log('zcard结果:', zcardResult);
93
+
94
+ const zscoreResult = await cache.zscore('test_zset', 'zmember1');
95
+ console.log('zscore结果:', zscoreResult);
96
+
97
+ const zrangebyscoreResult = await cache.zrangebyscore('test_zset', 0, 10);
98
+ console.log('zrangebyscore结果:', zrangebyscoreResult);
99
+ console.log('');
100
+
101
+ // 批量操作测试
102
+ console.log('=== 测试批量操作 ===');
103
+ const batchData = {
104
+ 'batch_key1': 'batch_value1',
105
+ 'batch_key2': 'batch_value2'
106
+ };
107
+ const msetResult = await cache.mset(batchData);
108
+ console.log('mset结果:', msetResult);
109
+ testKeys.push('batch_key1', 'batch_key2');
110
+
111
+ const mgetResult = await cache.mget(['batch_key1', 'batch_key2']);
112
+ console.log('mget结果:', mgetResult);
113
+ console.log('');
114
+
115
+ // 清理测试数据
116
+ console.log('=== 清理测试数据 ===');
117
+ for (const key of testKeys) {
118
+ await cache.del(key);
119
+ }
120
+ console.log('测试数据清理完成');
121
+ console.log('');
122
+
123
+ // 所有测试通过
124
+ console.log('✅ 所有Redis兼容API测试完成!');
125
+
126
+ // 关闭连接
127
+ await cache.close();
128
+ process.exit(0);
129
+
130
+ } catch (error) {
131
+ console.error('测试过程中出错:', error);
132
+
133
+ // 清理测试数据
134
+ if (cache && testKeys.length > 0) {
135
+ try {
136
+ console.log('尝试清理测试数据...');
137
+ for (const key of testKeys) {
138
+ await cache.del(key);
139
+ }
140
+ } catch (e) {
141
+ console.error('清理数据时出错:', e);
142
+ }
143
+ }
144
+
145
+ // 关闭连接
146
+ if (cache) {
147
+ await cache.close();
148
+ }
149
+
150
+ process.exit(1);
151
+ }
152
+ }
153
+
154
+ // 运行测试
155
+ runRedisCompatibilityTests();
@@ -1,122 +0,0 @@
1
- # 三种缓存方式方法兼容性对比表格
2
-
3
- ## 核心缓存方法
4
-
5
- | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
6
- |-------|-------|---------|-----------|----------|
7
- | set | ✅ | ✅ | ✅ | 所有方式均正常工作 |
8
- | get | ✅ | ✅ | ✅ | 所有方式均正常工作 |
9
- | del | ✅ | ✅ | ✅ | 所有方式均正常工作 |
10
- | has | ✅ | ✅ | ✅ | 所有方式均正常工作 |
11
- | clear | ✅ | ✅ | ✅ | 所有方式均正常工作 |
12
- | keys | ✅ | ✅ | ✅ | 所有方式均正常工作 |
13
- | ttl | ✅ | ✅ | ✅ | 所有方式均正常工作 |
14
- | add | ✅ | ✅ | ✅ | 所有方式均正常工作 |
15
- | addInt | ✅ | ✅ | ✅ | 所有方式均正常工作 |
16
- | addStr | ✅ | ✅ | ✅ | 所有方式均正常工作 |
17
- | sort | ✅ | ✅ | ✅ | 所有方式均正常工作 |
18
-
19
- ## Redis兼容方法 - 哈希表操作
20
-
21
- | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
22
- |-------|-------|---------|-----------|----------|
23
- | hset | ✅ | ✅ | ✅ | 所有方式均正常工作 |
24
- | hget | ✅ | ✅ | ✅ | 所有方式均正常工作 |
25
- | hgetall | ✅ | ✅ | ✅ | 所有方式均正常工作 |
26
- | hdel | ✅ | ✅ | ✅ | 所有方式均正常工作 |
27
- | hexists | ❌ | ❌ | ❌ | 已移除,测试确认不可用 |
28
- | hkeys | ❌ | ❌ | ❌ | 已移除 |
29
- | hvals | ❌ | ❌ | ❌ | 已移除 |
30
-
31
- ## Redis兼容方法 - 其他常用命令
32
-
33
- | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
34
- |-------|-------|---------|-----------|----------|
35
- | expire | ✅ | ✅ | ✅ | 所有方式均正常工作 |
36
- | incr | ✅ | ✅ | ✅ | 所有方式均返回正确数值 |
37
- | decr | ✅ | ✅ | ✅ | 所有方式均返回正确数值 |
38
- | exists | ✅ | ✅ | ✅ | 所有方式均正常工作 |
39
- | mget | ✅ | ✅ | ✅ | 所有方式均返回正确格式的数组 |
40
- | mset | ✅ | ✅ | ✅ | 所有方式均正常工作 |
41
-
42
- ## 数组/列表操作方法
43
-
44
- | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
45
- |-------|-------|---------|-----------|----------|
46
- | list_set | ❌ | ❌ | ❌ | 测试确认不支持 |
47
- | list_get | ❌ | ❌ | ❌ | 未测试,预计不支持 |
48
- | list_len | ❌ | ❌ | ❌ | 未测试,预计不支持 |
49
- | list_push | ❌ | ❌ | ❌ | 未测试,预计不支持 |
50
- | list_pop | ❌ | ❌ | ❌ | 未测试,预计不支持 |
51
-
52
- ## 全面兼容性测试结果总结
53
-
54
- 根据所有测试文件的运行结果,我们得到了全面的兼容性情况:
55
-
56
- ### 所有缓存方式都支持的功能:
57
- - **哈希表基本操作**:hset, hget, hgetall, hdel
58
- - **核心Redis命令**:set, get, expire, exists, mset
59
- - **缓存管理功能**:clear, keys, 缓存池, 缓存清理
60
- - **缓存方式切换**:可以在cachebase、redis、mongodb之间正常切换
61
-
62
- ### CacheBase 缓存方式:
63
- - **完全兼容**:所有测试都成功通过
64
- - **返回值**:所有操作都返回符合预期的结果
65
- - **数组操作**:不支持list_set等数组操作方法
66
-
67
- ### Redis 缓存方式:
68
- - **完全兼容**:所有测试都成功通过
69
- - **连接状态**:成功连接Redis服务器,连接池正常工作
70
- - **返回值**:incr/decr返回正确数值(11, 10)
71
- - **数组操作**:不支持list_set等数组操作方法
72
-
73
- ### MongoDB 缓存方式:
74
- - **功能执行成功**:所有操作都能正确修改数据
75
- - **返回值正常**:所有方法都返回符合Redis兼容格式的结果
76
- - **数组操作**:不支持list_set等数组操作方法
77
-
78
- ### 已确认移除的方法:
79
- - hexists:测试中报错 "TypeError: cache.hexists is not a function"
80
- - 所有列表/数组操作方法:测试中报错 "Error: 不支持的方法: list_set"
81
-
82
- ## 最佳使用建议
83
-
84
- 1. **CacheBase 方式**(推荐):
85
- - 所有功能完全兼容,返回值符合预期
86
- - 性能稳定,在多次依赖更新中保持一致表现
87
- - 适合所有缓存场景,特别是对稳定性要求高的情况
88
- - 不需要额外的外部服务依赖
89
-
90
- 2. **Redis 方式**(推荐):
91
- - 依赖更新后已修复兼容性问题,现在可以正常使用
92
- - 所有功能完全兼容,返回值符合预期
93
- - 适合需要高性能、分布式缓存或Redis特有功能的场景
94
- - 需要外部Redis服务
95
-
96
- 3. **MongoDB 方式**(推荐):
97
- - 可用于需要持久化且数据结构较简单的场景
98
- - **重要注意事项**:
99
- - 适合需要持久化缓存且需要Redis兼容API的场景
100
- - 所有Redis兼容方法都能返回正确格式的结果
101
- - 需要外部MongoDB服务
102
-
103
- ## 实际使用建议
104
-
105
- 1. **开发环境**:推荐使用CacheBase,无需额外配置,使用简单
106
-
107
- 2. **生产环境**:
108
- - 如果需要高性能、分布式缓存:使用Redis
109
- - 如果需要缓存持久化且已有MongoDB环境:可使用MongoDB
110
- - 大多数场景下,CacheBase已足够应对
111
-
112
- 3. **跨环境部署**:
113
- - 可以根据环境配置自动切换缓存方式
114
- - 确保代码不依赖特定缓存方式的返回值特性(特别是MongoDB)
115
-
116
- 4. **性能考虑**:
117
- - CacheBase:内存操作,最快但不持久化
118
- - Redis:网络操作,但性能优秀
119
- - MongoDB:网络+磁盘操作,性能相对较低
120
-
121
- ## 兼容性维护建议
122
- 注:✅ 完全兼容/功能正常 | ⚠️ 功能正常但返回值异常 | ❌ 不兼容/未实现/已移除