mm_mongodb 1.4.5 → 1.4.7
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 +154 -215
- package/compatibility_table.md +122 -0
- package/index.js +1494 -75
- package/package.json +1 -1
- package/test2.js +22 -14
- package/test_redis_api.js +66 -0
- package/test_redis_compatibility.js +123 -0
- package/cache.js +0 -2866
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# mm_mongodb
|
|
2
2
|
|
|
3
|
-
MongoDB数据库操作模块,提供了简洁易用的API
|
|
3
|
+
MongoDB数据库操作模块,提供了简洁易用的API、缓存功能以及**完整的Redis兼容接口**。
|
|
4
4
|
|
|
5
5
|
## 功能特点
|
|
6
6
|
|
|
7
|
-
- 支持MongoDB连接池管理
|
|
8
|
-
- 自动连接和重连机制
|
|
9
|
-
- 事务支持
|
|
10
|
-
- 索引管理
|
|
11
|
-
- 缓存功能
|
|
12
|
-
-
|
|
13
|
-
- 环境变量配置支持
|
|
14
|
-
- 完善的错误处理和重试机制
|
|
15
|
-
- 查询注入防护
|
|
16
|
-
- 事件系统:支持监听关键操作的事件
|
|
7
|
+
- ✅ 支持MongoDB连接池管理
|
|
8
|
+
- ✅ 自动连接和重连机制
|
|
9
|
+
- ✅ 事务支持
|
|
10
|
+
- ✅ 索引管理
|
|
11
|
+
- ✅ 缓存功能
|
|
12
|
+
- ✅ **完整的Redis兼容API**:支持Redis风格的键值操作、列表、集合、有序集合、哈希等数据类型
|
|
13
|
+
- ✅ 环境变量配置支持
|
|
14
|
+
- ✅ 完善的错误处理和重试机制
|
|
15
|
+
- ✅ 查询注入防护
|
|
16
|
+
- ✅ 事件系统:支持监听关键操作的事件
|
|
17
17
|
|
|
18
18
|
## 安装
|
|
19
19
|
|
|
@@ -140,260 +140,212 @@ await db.createIndex('users', { name: 1 }, { unique: true });
|
|
|
140
140
|
await db.createTTLIndex('logs', { createdAt: 1 }, 3600); // 3600秒后过期
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
## Redis兼容API使用指南
|
|
144
|
+
|
|
145
|
+
mm_mongodb提供了**完整的Redis兼容API**,使您可以使用熟悉的Redis命令与MongoDB进行交互。这对于从Redis迁移到MongoDB或在两者间切换使用非常有用。
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
### 快速开始
|
|
146
148
|
|
|
147
149
|
```javascript
|
|
148
150
|
const { mongodb_cache_admin } = require('mm_mongodb');
|
|
149
151
|
|
|
150
|
-
//
|
|
152
|
+
// 获取Redis兼容的缓存实例
|
|
151
153
|
const cache = mongodb_cache_admin('default');
|
|
152
154
|
|
|
153
|
-
//
|
|
155
|
+
// 连接数据库(重要:必须先连接)
|
|
154
156
|
await cache.open();
|
|
155
157
|
|
|
156
|
-
//
|
|
157
|
-
await cache.set('user_1', { id: 1, name: '王五' }, 10);
|
|
158
|
-
|
|
159
|
-
// 获取缓存
|
|
160
|
-
const user = await cache.get('user_1');
|
|
161
|
-
|
|
162
|
-
// 删除缓存
|
|
163
|
-
await cache.del('user_1');
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### 数值操作
|
|
167
|
-
|
|
168
|
-
```javascript
|
|
169
|
-
// 增加整数值
|
|
170
|
-
await cache.addInt('counter', 1); // 增加1
|
|
171
|
-
|
|
172
|
-
// 增加浮点数值
|
|
173
|
-
await cache.addFloat('score', 0.5); // 增加0.5
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
#### 数组操作
|
|
177
|
-
|
|
178
|
-
```javascript
|
|
179
|
-
// 设置数组
|
|
180
|
-
await cache.list_set('users', ['张三', '李四', '王五']);
|
|
181
|
-
|
|
182
|
-
// 添加到数组
|
|
183
|
-
await cache.list_push('users', '赵六');
|
|
184
|
-
|
|
185
|
-
// 获取数组
|
|
186
|
-
const users = await cache.list_get('users');
|
|
187
|
-
|
|
188
|
-
// 判断元素是否在数组中
|
|
189
|
-
const exists = await cache.list_has('users', '张三');
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
#### 过期时间管理
|
|
193
|
-
|
|
194
|
-
```javascript
|
|
195
|
-
// 设置过期时间(秒)
|
|
196
|
-
await cache.expire('temp_data', 300); // 5分钟后过期
|
|
197
|
-
|
|
198
|
-
// 获取剩余过期时间
|
|
199
|
-
const ttl = await cache.ttl('temp_data');
|
|
200
|
-
if (ttl === -1) console.log('永不过期');
|
|
201
|
-
else if (ttl === -2) console.log('键不存在');
|
|
202
|
-
else console.log(`剩余${ttl}秒过期`);
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## Redis兼容API使用指南
|
|
206
|
-
|
|
207
|
-
mm_mongodb提供了完整的Redis兼容API,使您可以使用熟悉的Redis命令与MongoDB进行交互。这对于从Redis迁移到MongoDB或在两者间切换使用非常有用。
|
|
208
|
-
|
|
209
|
-
### 基本键值操作
|
|
210
|
-
|
|
211
|
-
```javascript
|
|
212
|
-
// 设置键值(支持过期时间)
|
|
158
|
+
// 基本操作示例
|
|
213
159
|
await cache.set('name', 'Redis Compatible');
|
|
214
|
-
|
|
215
|
-
// 仅当键不存在时设置
|
|
216
|
-
await cache.setnx('counter', 1);
|
|
217
|
-
|
|
218
|
-
// 设置带过期时间的键(SET EX)
|
|
219
|
-
await cache.setex('temp_key', 60, '临时值');
|
|
220
|
-
|
|
221
|
-
// 获取键值
|
|
222
160
|
const value = await cache.get('name');
|
|
223
|
-
|
|
224
|
-
// 批量设置
|
|
225
|
-
await cache.mset({ 'key1': 'value1', 'key2': 'value2' });
|
|
226
|
-
|
|
227
|
-
// 批量获取
|
|
228
|
-
const values = await cache.mget('key1', 'key2', 'key3');
|
|
229
|
-
|
|
230
|
-
// 删除键
|
|
231
|
-
await cache.del('name');
|
|
232
|
-
|
|
233
|
-
// 批量删除键
|
|
234
|
-
await cache.delKeys('key1', 'key2');
|
|
235
|
-
|
|
236
|
-
// 判断键是否存在
|
|
237
|
-
const exists = await cache.has('name');
|
|
238
|
-
|
|
239
|
-
// 获取匹配的键名
|
|
240
|
-
const keys = await cache.keys('user:*');
|
|
241
161
|
```
|
|
242
162
|
|
|
243
|
-
###
|
|
163
|
+
### 核心缓存方法
|
|
164
|
+
|
|
165
|
+
| 方法名 | 说明 | 示例 |
|
|
166
|
+
|-------|------|------|
|
|
167
|
+
| `set(key, value, seconds)` | 设置键值,支持过期时间 | `await cache.set('name', 'value', 60);` |
|
|
168
|
+
| `get(key)` | 获取键值 | `const value = await cache.get('name');` |
|
|
169
|
+
| `del(key)` | 删除键 | `await cache.del('name');` |
|
|
170
|
+
| `has(key)` / `exists(key)` | 判断键是否存在 | `const exists = await cache.has('name');` |
|
|
171
|
+
| `clear(prefix)` | 清空缓存(可选前缀过滤) | `await cache.clear('temp:*');` |
|
|
172
|
+
| `keys(pattern)` | 获取匹配的键名 | `const keys = await cache.keys('user:*');` |
|
|
173
|
+
| `ttl(key)` | 获取剩余过期时间 | `const ttl = await cache.ttl('name');` |
|
|
174
|
+
| `expire(key, seconds)` | 设置过期时间 | `await cache.expire('name', 60);` |
|
|
175
|
+
| `add(key, value)` | 添加缓存(如果存在则不覆盖) | `await cache.add('counter', 1);` |
|
|
176
|
+
| `addInt(key, value)` | 增加整数值 | `await cache.addInt('counter', 10);` |
|
|
177
|
+
| `addFloat(key, value)` | 增加浮点数值 | `await cache.addFloat('score', 0.5);` |
|
|
178
|
+
| `addStr(key, value)` | 追加字符串 | `await cache.addStr('message', ' World');` |
|
|
179
|
+
| `sort(prefix, count, type)` | 排序并获取 | `const sorted = await cache.sort('user:*', 10, 'asc');` |
|
|
180
|
+
|
|
181
|
+
### 哈希表操作
|
|
244
182
|
|
|
245
183
|
```javascript
|
|
246
|
-
//
|
|
247
|
-
await cache.
|
|
184
|
+
// 设置哈希字段
|
|
185
|
+
await cache.hset('user:1', 'name', '张三');
|
|
248
186
|
|
|
249
|
-
//
|
|
250
|
-
const
|
|
187
|
+
// 获取哈希字段
|
|
188
|
+
const name = await cache.hget('user:1', 'name');
|
|
251
189
|
|
|
252
|
-
//
|
|
253
|
-
const
|
|
190
|
+
// 获取哈希所有字段和值
|
|
191
|
+
const user = await cache.hgetall('user:1');
|
|
254
192
|
|
|
255
|
-
//
|
|
256
|
-
await cache.
|
|
257
|
-
```
|
|
193
|
+
// 批量设置哈希字段
|
|
194
|
+
await cache.hmset('user:2', { name: '李四', age: 30 });
|
|
258
195
|
|
|
259
|
-
|
|
196
|
+
// 批量获取哈希字段
|
|
197
|
+
const values = await cache.hmget('user:2', 'name', 'age');
|
|
260
198
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
await cache.incr('counter'); // 自增1
|
|
199
|
+
// 删除哈希字段
|
|
200
|
+
await cache.hdel('user:1', 'name');
|
|
264
201
|
|
|
265
|
-
//
|
|
266
|
-
await cache.
|
|
202
|
+
// 批量删除哈希字段
|
|
203
|
+
await cache.hdelMulti('user:2', 'name', 'age');
|
|
267
204
|
|
|
268
|
-
//
|
|
269
|
-
await cache.
|
|
205
|
+
// 判断哈希字段是否存在
|
|
206
|
+
const exists = await cache.hexists('user:1', 'name');
|
|
270
207
|
|
|
271
|
-
//
|
|
272
|
-
await cache.
|
|
208
|
+
// 获取哈希字段数量
|
|
209
|
+
const count = await cache.hlen('user:1');
|
|
210
|
+
|
|
211
|
+
// 获取哈希所有字段名
|
|
212
|
+
const keys = await cache.hkeys('user:1');
|
|
213
|
+
|
|
214
|
+
// 获取哈希所有字段值
|
|
215
|
+
const vals = await cache.hvals('user:1');
|
|
273
216
|
```
|
|
274
217
|
|
|
275
218
|
### 列表操作
|
|
276
219
|
|
|
277
220
|
```javascript
|
|
278
221
|
// 从右侧推入元素
|
|
279
|
-
await cache.rpush('
|
|
222
|
+
await cache.rpush('messages', '你好');
|
|
280
223
|
|
|
281
224
|
// 从左侧推入元素
|
|
282
|
-
await cache.lpush('
|
|
225
|
+
await cache.lpush('messages', 'Hello');
|
|
283
226
|
|
|
284
227
|
// 获取列表长度
|
|
285
|
-
const length = await cache.llen('
|
|
228
|
+
const length = await cache.llen('messages');
|
|
286
229
|
|
|
287
230
|
// 获取列表指定范围的元素
|
|
288
|
-
const range = await cache.lrange('
|
|
231
|
+
const range = await cache.lrange('messages', 0, 1); // 获取前两个元素
|
|
289
232
|
|
|
290
233
|
// 获取列表指定索引的元素
|
|
291
|
-
const
|
|
234
|
+
const message = await cache.lindex('messages', 0);
|
|
292
235
|
|
|
293
236
|
// 从左侧弹出元素
|
|
294
|
-
const
|
|
237
|
+
const firstMessage = await cache.lpop('messages');
|
|
295
238
|
|
|
296
239
|
// 从右侧弹出元素
|
|
297
|
-
const
|
|
240
|
+
const lastMessage = await cache.rpop('messages');
|
|
298
241
|
|
|
299
242
|
// 修改列表指定索引的元素
|
|
300
|
-
await cache.lset('
|
|
243
|
+
await cache.lset('messages', 0, 'Updated Message');
|
|
301
244
|
|
|
302
245
|
// 删除列表中的元素
|
|
303
|
-
await cache.lrem('
|
|
246
|
+
await cache.lrem('messages', 2, 'value'); // 删除前2个值为'value'的元素
|
|
304
247
|
|
|
305
248
|
// 裁剪列表
|
|
306
|
-
await cache.ltrim('
|
|
249
|
+
await cache.ltrim('messages', 0, 4); // 保留前5个元素
|
|
307
250
|
```
|
|
308
251
|
|
|
309
252
|
### 集合操作
|
|
310
253
|
|
|
311
254
|
```javascript
|
|
312
255
|
// 添加集合成员
|
|
313
|
-
await cache.sadd('
|
|
256
|
+
await cache.sadd('users:online', 'user1');
|
|
314
257
|
|
|
315
258
|
// 批量添加集合成员
|
|
316
|
-
await cache.saddMulti('
|
|
259
|
+
await cache.saddMulti('users:online', 'user2', 'user3');
|
|
317
260
|
|
|
318
261
|
// 获取集合所有成员
|
|
319
|
-
const members = await cache.smembers('
|
|
262
|
+
const members = await cache.smembers('users:online');
|
|
320
263
|
|
|
321
264
|
// 判断成员是否在集合中
|
|
322
|
-
const
|
|
265
|
+
const isOnline = await cache.sismember('users:online', 'user1');
|
|
323
266
|
|
|
324
267
|
// 获取集合成员数量
|
|
325
|
-
const count = await cache.scard('
|
|
268
|
+
const count = await cache.scard('users:online');
|
|
326
269
|
|
|
327
270
|
// 移除集合成员
|
|
328
|
-
await cache.srem('
|
|
271
|
+
await cache.srem('users:online', 'user1');
|
|
329
272
|
|
|
330
273
|
// 批量移除集合成员
|
|
331
|
-
await cache.sremMulti('
|
|
274
|
+
await cache.sremMulti('users:online', 'user2', 'user3');
|
|
332
275
|
|
|
333
276
|
// 计算两个集合的差集
|
|
334
|
-
const
|
|
277
|
+
const offlineUsers = await cache.sdiff('users:all', 'users:online');
|
|
335
278
|
|
|
336
279
|
// 计算两个集合的交集
|
|
337
|
-
const
|
|
280
|
+
const activeUsers = await cache.sinter('users:online', 'users:paid');
|
|
338
281
|
|
|
339
282
|
// 计算两个集合的并集
|
|
340
|
-
const
|
|
283
|
+
const allUsers = await cache.sunion('users:online', 'users:offline');
|
|
341
284
|
```
|
|
342
285
|
|
|
343
|
-
###
|
|
286
|
+
### 有序集合操作
|
|
344
287
|
|
|
345
288
|
```javascript
|
|
346
|
-
//
|
|
347
|
-
await cache.
|
|
289
|
+
// 添加有序集合成员
|
|
290
|
+
await cache.zadd('ranking', 'user1', 100);
|
|
348
291
|
|
|
349
|
-
//
|
|
350
|
-
const
|
|
292
|
+
// 获取有序集合成员数量
|
|
293
|
+
const count = await cache.zcard('ranking');
|
|
351
294
|
|
|
352
|
-
//
|
|
353
|
-
const
|
|
295
|
+
// 获取有序集合成员分数
|
|
296
|
+
const score = await cache.zscore('ranking', 'user1');
|
|
354
297
|
|
|
355
|
-
//
|
|
356
|
-
await cache.
|
|
357
|
-
|
|
358
|
-
// 批量获取哈希字段
|
|
359
|
-
const values = await cache.hmget('hash', 'field1', 'field2', 'field3');
|
|
298
|
+
// 按分数范围获取有序集合成员
|
|
299
|
+
const topUsers = await cache.zrangebyscore('ranking', 0, 100);
|
|
360
300
|
|
|
361
|
-
//
|
|
362
|
-
await cache.
|
|
301
|
+
// 移除有序集合成员
|
|
302
|
+
await cache.zrem('ranking', 'user1');
|
|
303
|
+
```
|
|
363
304
|
|
|
364
|
-
|
|
365
|
-
await cache.hdelMulti('hash', 'field2', 'field3');
|
|
305
|
+
### 批量操作
|
|
366
306
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// 获取哈希字段数量
|
|
371
|
-
const count = await cache.hlen('hash');
|
|
307
|
+
```javascript
|
|
308
|
+
// 批量设置键值
|
|
309
|
+
await cache.mset({ 'key1': 'value1', 'key2': 'value2' });
|
|
372
310
|
|
|
373
|
-
//
|
|
374
|
-
const
|
|
311
|
+
// 批量获取键值
|
|
312
|
+
const values = await cache.mget('key1', 'key2', 'key3');
|
|
375
313
|
|
|
376
|
-
//
|
|
377
|
-
|
|
314
|
+
// 批量删除键
|
|
315
|
+
await cache.del('key1', 'key2', 'key3');
|
|
378
316
|
```
|
|
379
317
|
|
|
380
|
-
###
|
|
318
|
+
### 数值操作
|
|
381
319
|
|
|
382
320
|
```javascript
|
|
383
|
-
//
|
|
384
|
-
await cache.
|
|
321
|
+
// 原子递增
|
|
322
|
+
await cache.incr('counter'); // 自增1
|
|
385
323
|
|
|
386
|
-
//
|
|
387
|
-
|
|
324
|
+
// 原子递减
|
|
325
|
+
await cache.decr('counter'); // 自减1
|
|
388
326
|
|
|
389
|
-
//
|
|
390
|
-
|
|
327
|
+
// 增加指定整数
|
|
328
|
+
await cache.addInt('counter', 10); // 增加10
|
|
329
|
+
|
|
330
|
+
// 减少指定整数
|
|
331
|
+
await cache.addInt('counter', -5); // 减少5
|
|
391
332
|
```
|
|
392
333
|
|
|
393
334
|
## 事件系统
|
|
394
335
|
|
|
395
336
|
mm_mongodb的缓存模块实现了事件系统,可以监听各种操作的发生。增删改类方法会触发相应的事件,而查询类方法不触发事件以提高性能。
|
|
396
337
|
|
|
338
|
+
### 事件命名规范
|
|
339
|
+
|
|
340
|
+
所有事件严格遵循以下命名格式:
|
|
341
|
+
- 操作前事件:`action_before`
|
|
342
|
+
- 操作后事件:`action_after`
|
|
343
|
+
- 操作错误事件:`action_error`
|
|
344
|
+
|
|
345
|
+
其中`action`为方法名,例如`set`、`del`、`add`等。
|
|
346
|
+
|
|
347
|
+
### 事件示例
|
|
348
|
+
|
|
397
349
|
```javascript
|
|
398
350
|
// 监听事件
|
|
399
351
|
cache.on('set_before', (data) => {
|
|
@@ -411,25 +363,36 @@ cache.on('set_error', (data) => {
|
|
|
411
363
|
|
|
412
364
|
### 支持事件的方法
|
|
413
365
|
|
|
414
|
-
|
|
366
|
+
以下增删改类方法支持事件触发,每种方法都会触发对应的`action_before`、`action_after`和`action_error`事件:
|
|
415
367
|
|
|
416
|
-
- 原子操作:incr, decr,
|
|
368
|
+
- 原子操作:incr, decr, addInt, addFloat
|
|
417
369
|
- 字符串操作:append, addStr
|
|
418
|
-
- 列表操作:rpush, lpush, lset, lrem, ltrim
|
|
370
|
+
- 列表操作:rpush, lpush, lset, lrem, ltrim, lpop, rpop
|
|
419
371
|
- 集合操作:sadd, saddMulti, srem, sremMulti
|
|
420
372
|
- 哈希操作:hset, hmset, hdel, hdelMulti
|
|
421
|
-
-
|
|
373
|
+
- 有序集合操作:zadd, zrem
|
|
374
|
+
- 键操作:set, del, expire, mset, add
|
|
375
|
+
|
|
376
|
+
### 事件参数
|
|
377
|
+
|
|
378
|
+
事件回调函数接收的参数通常包含以下信息:
|
|
379
|
+
- 操作涉及的键(key)
|
|
380
|
+
- 操作涉及的值(value)
|
|
381
|
+
- 操作结果(仅在after事件中)
|
|
382
|
+
- 错误信息(仅在error事件中)
|
|
383
|
+
|
|
384
|
+
具体参数结构取决于触发事件的方法类型。
|
|
422
385
|
|
|
423
386
|
## 性能优化建议
|
|
424
387
|
|
|
425
388
|
1. **使用连接池**:优先使用`mongodb_admin`和`mongodb_cache_admin`创建的连接池实例
|
|
426
389
|
2. **合理设置索引**:为常用查询字段创建索引
|
|
427
390
|
3. **查询优化**:避免全表扫描,使用精确查询
|
|
428
|
-
4. **批量操作**:优先使用批量操作方法如`
|
|
391
|
+
4. **批量操作**:优先使用批量操作方法如`mset`、`mget`等
|
|
429
392
|
5. **过期时间**:为临时数据设置合理的过期时间,避免数据膨胀
|
|
430
|
-
6.
|
|
393
|
+
6. **Redis兼容模式**:使用字符串键名可以简化操作,与Redis保持一致的使用体验
|
|
431
394
|
|
|
432
|
-
## 迁移指南
|
|
395
|
+
## 从Redis迁移指南
|
|
433
396
|
|
|
434
397
|
从Redis迁移到使用mm_mongodb的Redis兼容API时,只需以下步骤:
|
|
435
398
|
|
|
@@ -442,6 +405,7 @@ cache.on('set_error', (data) => {
|
|
|
442
405
|
// Redis客户端示例
|
|
443
406
|
// const redis = require('redis');
|
|
444
407
|
// const client = redis.createClient();
|
|
408
|
+
// await client.connect();
|
|
445
409
|
|
|
446
410
|
// mm_mongodb替换示例
|
|
447
411
|
const { mongodb_cache_admin } = require('mm_mongodb');
|
|
@@ -502,46 +466,17 @@ new MongoDB(scope = 'default', dir = '', config = {})
|
|
|
502
466
|
- `getIndexes(tableName)`:获取索引信息
|
|
503
467
|
- `dropIndex(tableName, indexName)`:删除索引
|
|
504
468
|
|
|
505
|
-
###
|
|
506
|
-
|
|
507
|
-
#### 基本操作
|
|
508
|
-
|
|
509
|
-
- `get(key)`:获取缓存
|
|
510
|
-
- `set(key, value, seconds)`:设置缓存
|
|
511
|
-
- `add(key, value, seconds)`:添加缓存(如果存在则不覆盖)
|
|
512
|
-
- `del(key)`:删除缓存
|
|
513
|
-
- `has(key)`:判断键是否存在
|
|
514
|
-
- `clear(prefix)`:清空缓存(可选前缀过滤)
|
|
515
|
-
|
|
516
|
-
#### 数值操作
|
|
517
|
-
|
|
518
|
-
- `addInt(key, value)`:增加整数值
|
|
519
|
-
- `addFloat(key, value)`:增加浮点数值
|
|
520
|
-
- `addStr(key, value)`:追加字符串
|
|
521
|
-
|
|
522
|
-
#### 数组操作
|
|
523
|
-
|
|
524
|
-
- `list_set(key, value, seconds)`:设置数组
|
|
525
|
-
- `list_push(key, value)`:添加到数组
|
|
526
|
-
- `list_get(key, start, end)`:获取数组片段
|
|
527
|
-
- `list_has(key, value)`:判断元素是否在数组中
|
|
528
|
-
- `list_clear(key, value)`:清空数组
|
|
469
|
+
### Redis兼容API
|
|
529
470
|
|
|
530
|
-
|
|
471
|
+
详细的Redis兼容API见上方「Redis兼容API使用指南」章节。支持以下类别的API:
|
|
531
472
|
|
|
532
|
-
-
|
|
533
|
-
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
-
|
|
538
|
-
-
|
|
539
|
-
- `setrange(key, index, value)`:设置字符串范围
|
|
540
|
-
- `sort(prefix, count, type)`:排序并获取
|
|
541
|
-
|
|
542
|
-
#### Redis兼容API
|
|
543
|
-
|
|
544
|
-
详细的Redis兼容API见上方「Redis兼容API使用指南」章节。
|
|
473
|
+
- **核心缓存方法**:set, get, del, has, exists, clear, keys, ttl, expire等
|
|
474
|
+
- **哈希表操作**:hset, hget, hgetall, hmset, hmget, hdel, hdelMulti, hexists, hkeys, hvals, hlen等
|
|
475
|
+
- **列表操作**:rpush, lpush, lrange, lindex, llen, lpop, rpop, lset, lrem, ltrim等
|
|
476
|
+
- **集合操作**:sadd, saddMulti, srem, sremMulti, smembers, scard, sismember, sdiff, sinter, sunion等
|
|
477
|
+
- **有序集合操作**:zadd, zrem, zrangebyscore, zscore, zcard等
|
|
478
|
+
- **批量操作**:mget, mset等
|
|
479
|
+
- **数值操作**:incr, decr, addInt, addFloat等
|
|
545
480
|
|
|
546
481
|
## 安全注意事项
|
|
547
482
|
|
|
@@ -551,6 +486,10 @@ new MongoDB(scope = 'default', dir = '', config = {})
|
|
|
551
486
|
4. 连接错误时会自动重试,提高稳定性
|
|
552
487
|
5. 避免使用未经处理的用户输入作为查询条件
|
|
553
488
|
|
|
489
|
+
## 兼容性表格
|
|
490
|
+
|
|
491
|
+
查看详细的方法兼容性对比表格,请参考项目中的 [compatibility_table.md](https://github.com/qwwang/mm_mongodb/blob/main/compatibility_table.md) 文件。
|
|
492
|
+
|
|
554
493
|
## 依赖
|
|
555
494
|
|
|
556
495
|
- [mm_logs](https://www.npmjs.com/package/mm_logs):日志模块
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
注:✅ 完全兼容/功能正常 | ⚠️ 功能正常但返回值异常 | ❌ 不兼容/未实现/已移除
|