monsqlize 1.0.0
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/CHANGELOG.md +2474 -0
- package/LICENSE +21 -0
- package/README.md +1368 -0
- package/index.d.ts +1052 -0
- package/lib/cache.js +491 -0
- package/lib/common/cursor.js +58 -0
- package/lib/common/docs-urls.js +72 -0
- package/lib/common/index-options.js +222 -0
- package/lib/common/log.js +60 -0
- package/lib/common/namespace.js +21 -0
- package/lib/common/normalize.js +33 -0
- package/lib/common/page-result.js +42 -0
- package/lib/common/runner.js +56 -0
- package/lib/common/server-features.js +231 -0
- package/lib/common/shape-builders.js +26 -0
- package/lib/common/validation.js +49 -0
- package/lib/connect.js +76 -0
- package/lib/constants.js +54 -0
- package/lib/count-queue.js +187 -0
- package/lib/distributed-cache-invalidator.js +259 -0
- package/lib/errors.js +157 -0
- package/lib/index.js +352 -0
- package/lib/logger.js +224 -0
- package/lib/model/examples/test.js +114 -0
- package/lib/mongodb/common/accessor-helpers.js +44 -0
- package/lib/mongodb/common/agg-pipeline.js +32 -0
- package/lib/mongodb/common/iid.js +27 -0
- package/lib/mongodb/common/lexicographic-expr.js +52 -0
- package/lib/mongodb/common/shape.js +31 -0
- package/lib/mongodb/common/sort.js +38 -0
- package/lib/mongodb/common/transaction-aware.js +24 -0
- package/lib/mongodb/connect.js +178 -0
- package/lib/mongodb/index.js +458 -0
- package/lib/mongodb/management/admin-ops.js +199 -0
- package/lib/mongodb/management/bookmark-ops.js +166 -0
- package/lib/mongodb/management/cache-ops.js +49 -0
- package/lib/mongodb/management/collection-ops.js +386 -0
- package/lib/mongodb/management/database-ops.js +201 -0
- package/lib/mongodb/management/index-ops.js +474 -0
- package/lib/mongodb/management/index.js +16 -0
- package/lib/mongodb/management/namespace.js +30 -0
- package/lib/mongodb/management/validation-ops.js +267 -0
- package/lib/mongodb/queries/aggregate.js +133 -0
- package/lib/mongodb/queries/chain.js +623 -0
- package/lib/mongodb/queries/count.js +88 -0
- package/lib/mongodb/queries/distinct.js +68 -0
- package/lib/mongodb/queries/find-and-count.js +183 -0
- package/lib/mongodb/queries/find-by-ids.js +235 -0
- package/lib/mongodb/queries/find-one-by-id.js +170 -0
- package/lib/mongodb/queries/find-one.js +61 -0
- package/lib/mongodb/queries/find-page.js +565 -0
- package/lib/mongodb/queries/find.js +161 -0
- package/lib/mongodb/queries/index.js +49 -0
- package/lib/mongodb/writes/delete-many.js +181 -0
- package/lib/mongodb/writes/delete-one.js +173 -0
- package/lib/mongodb/writes/find-one-and-delete.js +193 -0
- package/lib/mongodb/writes/find-one-and-replace.js +222 -0
- package/lib/mongodb/writes/find-one-and-update.js +223 -0
- package/lib/mongodb/writes/increment-one.js +243 -0
- package/lib/mongodb/writes/index.js +41 -0
- package/lib/mongodb/writes/insert-batch.js +498 -0
- package/lib/mongodb/writes/insert-many.js +218 -0
- package/lib/mongodb/writes/insert-one.js +171 -0
- package/lib/mongodb/writes/replace-one.js +199 -0
- package/lib/mongodb/writes/result-handler.js +236 -0
- package/lib/mongodb/writes/update-many.js +205 -0
- package/lib/mongodb/writes/update-one.js +207 -0
- package/lib/mongodb/writes/upsert-one.js +190 -0
- package/lib/multi-level-cache.js +189 -0
- package/lib/operators.js +330 -0
- package/lib/redis-cache-adapter.js +237 -0
- package/lib/transaction/CacheLockManager.js +161 -0
- package/lib/transaction/DistributedCacheLockManager.js +239 -0
- package/lib/transaction/Transaction.js +314 -0
- package/lib/transaction/TransactionManager.js +266 -0
- package/lib/transaction/index.js +10 -0
- package/package.json +111 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,1052 @@
|
|
|
1
|
+
declare module 'monsqlize' {
|
|
2
|
+
type DbType = 'mongodb';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 日志记录器接口
|
|
6
|
+
* v2.0 新增:支持 traceId 和结构化日志
|
|
7
|
+
*/
|
|
8
|
+
interface LoggerLike {
|
|
9
|
+
debug?: (...args: any[]) => void;
|
|
10
|
+
info?: (...args: any[]) => void;
|
|
11
|
+
warn?: (...args: any[]) => void;
|
|
12
|
+
error?: (...args: any[]) => void;
|
|
13
|
+
withTraceId?: (fn: Function, traceId?: string) => any;
|
|
14
|
+
getTraceId?: () => string | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 日志选项
|
|
19
|
+
*/
|
|
20
|
+
interface LoggerOptions {
|
|
21
|
+
/** 是否使用结构化日志(JSON 格式) */
|
|
22
|
+
structured?: boolean;
|
|
23
|
+
/** 是否启用 traceId(分布式追踪) */
|
|
24
|
+
enableTraceId?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 统一错误码
|
|
29
|
+
*/
|
|
30
|
+
const enum ErrorCodes {
|
|
31
|
+
VALIDATION_ERROR = 'VALIDATION_ERROR',
|
|
32
|
+
INVALID_COLLECTION_NAME = 'INVALID_COLLECTION_NAME',
|
|
33
|
+
INVALID_DATABASE_NAME = 'INVALID_DATABASE_NAME',
|
|
34
|
+
INVALID_CURSOR = 'INVALID_CURSOR',
|
|
35
|
+
CURSOR_SORT_MISMATCH = 'CURSOR_SORT_MISMATCH',
|
|
36
|
+
JUMP_TOO_FAR = 'JUMP_TOO_FAR',
|
|
37
|
+
STREAM_NO_JUMP = 'STREAM_NO_JUMP',
|
|
38
|
+
STREAM_NO_TOTALS = 'STREAM_NO_TOTALS',
|
|
39
|
+
CONNECTION_TIMEOUT = 'CONNECTION_TIMEOUT',
|
|
40
|
+
CONNECTION_FAILED = 'CONNECTION_FAILED',
|
|
41
|
+
CONNECTION_CLOSED = 'CONNECTION_CLOSED',
|
|
42
|
+
DATABASE_ERROR = 'DATABASE_ERROR',
|
|
43
|
+
QUERY_TIMEOUT = 'QUERY_TIMEOUT',
|
|
44
|
+
CACHE_ERROR = 'CACHE_ERROR',
|
|
45
|
+
CACHE_TIMEOUT = 'CACHE_TIMEOUT',
|
|
46
|
+
INVALID_CONFIG = 'INVALID_CONFIG',
|
|
47
|
+
UNSUPPORTED_DATABASE = 'UNSUPPORTED_DATABASE',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// 事务相关类型定义(Transaction API)
|
|
52
|
+
// ============================================================================
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* MongoDB 事务会话(原生 ClientSession)
|
|
56
|
+
* @since v0.2.0
|
|
57
|
+
*/
|
|
58
|
+
interface MongoSession {
|
|
59
|
+
/** 会话 ID */
|
|
60
|
+
id: any;
|
|
61
|
+
/** 是否在事务中 */
|
|
62
|
+
inTransaction(): boolean;
|
|
63
|
+
/** 事务状态 */
|
|
64
|
+
transaction?: {
|
|
65
|
+
state: string;
|
|
66
|
+
};
|
|
67
|
+
/** 结束会话 */
|
|
68
|
+
endSession(): void;
|
|
69
|
+
/** 其他 MongoDB 原生方法 */
|
|
70
|
+
[key: string]: any;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 事务选项配置
|
|
75
|
+
* @since v0.2.0
|
|
76
|
+
*/
|
|
77
|
+
interface TransactionOptions {
|
|
78
|
+
/** 读关注级别(Read Concern) */
|
|
79
|
+
readConcern?: {
|
|
80
|
+
level: 'local' | 'majority' | 'snapshot' | 'linearizable' | 'available';
|
|
81
|
+
};
|
|
82
|
+
/** 读偏好(Read Preference) */
|
|
83
|
+
readPreference?: 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest';
|
|
84
|
+
/** 因果一致性(Causal Consistency) */
|
|
85
|
+
causalConsistency?: boolean;
|
|
86
|
+
/** 事务最大执行时间(毫秒) */
|
|
87
|
+
maxDuration?: number;
|
|
88
|
+
/** 是否启用自动重试 */
|
|
89
|
+
enableRetry?: boolean;
|
|
90
|
+
/** 最大重试次数 */
|
|
91
|
+
maxRetries?: number;
|
|
92
|
+
/** 重试延迟(毫秒) */
|
|
93
|
+
retryDelay?: number;
|
|
94
|
+
/** 重试退避系数 */
|
|
95
|
+
retryBackoff?: number;
|
|
96
|
+
/** 是否启用缓存锁 */
|
|
97
|
+
enableCacheLock?: boolean;
|
|
98
|
+
/** 缓存锁清理间隔(毫秒) */
|
|
99
|
+
lockCleanupInterval?: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Transaction 事务类
|
|
104
|
+
* 封装 MongoDB 原生会话,提供事务生命周期管理
|
|
105
|
+
* @since v0.2.0
|
|
106
|
+
*/
|
|
107
|
+
interface Transaction {
|
|
108
|
+
/** 事务唯一 ID */
|
|
109
|
+
readonly id: string;
|
|
110
|
+
|
|
111
|
+
/** MongoDB 原生会话对象(传递给查询方法) */
|
|
112
|
+
readonly session: MongoSession;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 启动事务
|
|
116
|
+
* @returns Promise<void>
|
|
117
|
+
*/
|
|
118
|
+
start(): Promise<void>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 提交事务
|
|
122
|
+
* @returns Promise<void>
|
|
123
|
+
*/
|
|
124
|
+
commit(): Promise<void>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 中止(回滚)事务
|
|
128
|
+
* @returns Promise<void>
|
|
129
|
+
*/
|
|
130
|
+
abort(): Promise<void>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 结束会话(清理资源)
|
|
134
|
+
* @returns Promise<void>
|
|
135
|
+
*/
|
|
136
|
+
end(): Promise<void>;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 获取事务执行时长(毫秒)
|
|
140
|
+
* @returns number
|
|
141
|
+
*/
|
|
142
|
+
getDuration(): number;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 获取事务信息
|
|
146
|
+
* @returns 事务状态信息
|
|
147
|
+
*/
|
|
148
|
+
getInfo(): {
|
|
149
|
+
id: string;
|
|
150
|
+
status: 'pending' | 'started' | 'committed' | 'aborted';
|
|
151
|
+
duration: number;
|
|
152
|
+
sessionId: string;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 标准错误接口
|
|
158
|
+
*/
|
|
159
|
+
interface MonSQLizeError extends Error {
|
|
160
|
+
code: string;
|
|
161
|
+
details?: any[];
|
|
162
|
+
cause?: Error;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
interface CacheLike {
|
|
166
|
+
get(key: string): Promise<any>;
|
|
167
|
+
set(key: string, val: any, ttl?: number): Promise<void>;
|
|
168
|
+
del(key: string): Promise<boolean>;
|
|
169
|
+
exists(key: string): Promise<boolean>;
|
|
170
|
+
getMany(keys: string[]): Promise<Record<string, any>>;
|
|
171
|
+
setMany(obj: Record<string, any>, ttl?: number): Promise<boolean>;
|
|
172
|
+
delMany(keys: string[]): Promise<number>;
|
|
173
|
+
delPattern(pattern: string): Promise<number>;
|
|
174
|
+
clear(): void;
|
|
175
|
+
keys(pattern?: string): string[];
|
|
176
|
+
getStats?(): any;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 内置内存缓存的配置(MemoryCacheOptions)
|
|
181
|
+
* - maxSize: 最大键数量(默认 100000)
|
|
182
|
+
* - maxMemory: 最大内存占用(字节;0 表示不限制)
|
|
183
|
+
* - enableStats: 是否启用统计,默认 true
|
|
184
|
+
*/
|
|
185
|
+
interface MemoryCacheOptions {
|
|
186
|
+
maxSize?: number;
|
|
187
|
+
maxMemory?: number;
|
|
188
|
+
enableStats?: boolean;
|
|
189
|
+
// 允许透传其他实现细节,但不做强约束
|
|
190
|
+
[k: string]: any;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 多层缓存写策略
|
|
195
|
+
* - both:本地+远端双写(等待远端完成)
|
|
196
|
+
* - local-first-async-remote:本地先返回,远端异步写(降低尾延迟)
|
|
197
|
+
*/
|
|
198
|
+
type WritePolicy = 'both' | 'local-first-async-remote';
|
|
199
|
+
|
|
200
|
+
interface MultiLevelCachePolicy {
|
|
201
|
+
writePolicy?: WritePolicy;
|
|
202
|
+
/** 远端命中后是否回填本地,默认 true */
|
|
203
|
+
backfillLocalOnRemoteHit?: boolean;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 多层缓存配置对象(配置式启用双层缓存)
|
|
208
|
+
* 说明:当 BaseOptions.cache 传入该对象时(且 multiLevel=true),框架会自动创建 MultiLevelCache:
|
|
209
|
+
* - local:始终使用内置内存缓存(仅接受配置对象 MemoryCacheOptions)
|
|
210
|
+
* - remote:可传 CacheLike 实例(推荐生产),或传配置对象以退化为“内存占位”
|
|
211
|
+
* - remote.timeoutMs:远端操作超时(毫秒,默认 50)
|
|
212
|
+
* - publish:可选的广播函数(例如用于 pub/sub 触发跨进程本地失效)
|
|
213
|
+
*/
|
|
214
|
+
interface MultiLevelCacheOptions {
|
|
215
|
+
multiLevel: true;
|
|
216
|
+
local?: MemoryCacheOptions;
|
|
217
|
+
remote?: CacheLike | (MemoryCacheOptions & { timeoutMs?: number });
|
|
218
|
+
policy?: MultiLevelCachePolicy;
|
|
219
|
+
publish?: (msg: any) => void;
|
|
220
|
+
}
|
|
221
|
+
interface BaseOptions {
|
|
222
|
+
type: DbType;
|
|
223
|
+
databaseName: string;
|
|
224
|
+
config: any;
|
|
225
|
+
cache?: CacheLike | MemoryCacheOptions | MultiLevelCacheOptions | object;
|
|
226
|
+
logger?: LoggerLike;
|
|
227
|
+
maxTimeMS?: number; // 全局默认查询超时(毫秒)
|
|
228
|
+
findLimit?: number; // 全局默认 find limit(未传 limit 时使用;0 表示不限制)
|
|
229
|
+
namespace?: { instanceId?: string; scope?: 'database' | 'connection' };
|
|
230
|
+
slowQueryMs?: number; // 慢查询日志阈值(毫秒),默认 500
|
|
231
|
+
/** MongoDB 副本集读偏好(全局配置)
|
|
232
|
+
* - 'primary': 仅读主节点(默认)
|
|
233
|
+
* - 'primaryPreferred': 优先读主节点,主节点不可用时读从节点
|
|
234
|
+
* - 'secondary': 仅读从节点
|
|
235
|
+
* - 'secondaryPreferred': 优先读从节点,从节点不可用时读主节点
|
|
236
|
+
* - 'nearest': 读最近的节点(低延迟)
|
|
237
|
+
*/
|
|
238
|
+
readPreference?: 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest';
|
|
239
|
+
/**
|
|
240
|
+
* 事务配置(MongoDB Transaction API)
|
|
241
|
+
* 需要 MongoDB 4.0+ 且部署在副本集或分片集群上
|
|
242
|
+
* @since v0.2.0
|
|
243
|
+
*/
|
|
244
|
+
transaction?: TransactionOptions | false;
|
|
245
|
+
// 统一默认(新增可选项)
|
|
246
|
+
findPageMaxLimit?: number; // 深分页页大小上限(默认 500)
|
|
247
|
+
cursorSecret?: string; // 可选:游标签名密钥(如启用 HMAC 验签)
|
|
248
|
+
log?: {
|
|
249
|
+
slowQueryTag?: { event?: string; code?: string };
|
|
250
|
+
formatSlowQuery?: (meta: any) => any;
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
interface FindOptions {
|
|
254
|
+
projection?: Record<string, any> | string[];
|
|
255
|
+
sort?: Record<string, 1 | -1>;
|
|
256
|
+
limit?: number;
|
|
257
|
+
skip?: number;
|
|
258
|
+
cache?: number;
|
|
259
|
+
maxTimeMS?: number;
|
|
260
|
+
/** Mongo-only: 透传 hint 到驱动 */
|
|
261
|
+
hint?: any;
|
|
262
|
+
/** Mongo-only: 透传 collation 到驱动 */
|
|
263
|
+
collation?: any;
|
|
264
|
+
/** 查询注释(用于生产环境日志跟踪)*/
|
|
265
|
+
comment?: string;
|
|
266
|
+
meta?: boolean | MetaOptions; // 返回耗时元信息
|
|
267
|
+
}
|
|
268
|
+
interface CountOptions {
|
|
269
|
+
cache?: number;
|
|
270
|
+
maxTimeMS?: number;
|
|
271
|
+
/** Mongo-only: 透传 hint 到 countDocuments */
|
|
272
|
+
hint?: any;
|
|
273
|
+
/** Mongo-only: 透传 collation 到 countDocuments */
|
|
274
|
+
collation?: any;
|
|
275
|
+
/** 查询注释(用于生产环境日志跟踪)*/
|
|
276
|
+
comment?: string;
|
|
277
|
+
meta?: boolean | MetaOptions;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
interface AggregateOptions {
|
|
281
|
+
cache?: number; // 缓存时间(毫秒),默认 0(不缓存)
|
|
282
|
+
maxTimeMS?: number; // 查询超时时间(毫秒)
|
|
283
|
+
allowDiskUse?: boolean; // 是否允许使用磁盘(默认 false)
|
|
284
|
+
collation?: any; // 排序规则(可选)
|
|
285
|
+
hint?: string | object; // 索引提示(可选)
|
|
286
|
+
comment?: string; // 查询注释(可选)
|
|
287
|
+
meta?: boolean | MetaOptions; // 返回耗时元信息
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
interface DistinctOptions {
|
|
291
|
+
cache?: number; // 缓存时间(毫秒),默认继承实例缓存配置
|
|
292
|
+
maxTimeMS?: number; // 查询超时时间(毫秒)
|
|
293
|
+
collation?: any; // 排序规则(可选)
|
|
294
|
+
hint?: string | object; // 索引提示(可选)
|
|
295
|
+
meta?: boolean | MetaOptions; // 返回耗时元信息
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 写入操作相关接口
|
|
299
|
+
interface WriteConcern {
|
|
300
|
+
w?: number | 'majority'; // 写确认级别(默认 1)
|
|
301
|
+
j?: boolean; // 是否等待日志落盘(默认 false)
|
|
302
|
+
wtimeout?: number; // 写超时时间(毫秒)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
interface InsertOneOptions {
|
|
306
|
+
document: any; // 要插入的文档
|
|
307
|
+
writeConcern?: WriteConcern; // 写确认级别(可选)
|
|
308
|
+
bypassDocumentValidation?: boolean; // 跳过文档验证(可选)
|
|
309
|
+
comment?: string; // 查询注释(用于生产环境日志跟踪)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
interface InsertOneResult {
|
|
313
|
+
acknowledged: boolean; // 是否被确认
|
|
314
|
+
insertedId: any; // 插入的文档 _id
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
interface InsertManyOptions {
|
|
318
|
+
documents: any[]; // 要插入的文档数组
|
|
319
|
+
ordered?: boolean; // 是否有序插入(默认 true)
|
|
320
|
+
writeConcern?: WriteConcern; // 写确认级别(可选)
|
|
321
|
+
bypassDocumentValidation?: boolean; // 跳过文档验证(可选)
|
|
322
|
+
comment?: string; // 查询注释(用于生产环境日志跟踪)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface InsertManyResult {
|
|
326
|
+
acknowledged: boolean; // 是否被确认
|
|
327
|
+
insertedCount: number; // 成功插入的文档数量
|
|
328
|
+
insertedIds: { [key: number]: any }; // 插入的文档 _id 映射表
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
interface StreamOptions {
|
|
332
|
+
projection?: Record<string, any> | string[]; // 字段投影
|
|
333
|
+
sort?: Record<string, 1 | -1>; // 排序配置
|
|
334
|
+
limit?: number; // 限制返回数量
|
|
335
|
+
skip?: number; // 跳过数量
|
|
336
|
+
batchSize?: number; // 每批次大小(默认 1000)
|
|
337
|
+
maxTimeMS?: number; // 查询超时时间(毫秒)
|
|
338
|
+
hint?: any; // 索引提示
|
|
339
|
+
collation?: any; // 排序规则
|
|
340
|
+
noCursorTimeout?: boolean; // 禁用游标超时(默认 false)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Explain 选项(查询执行计划诊断)
|
|
344
|
+
interface ExplainOptions {
|
|
345
|
+
projection?: object; // 字段投影
|
|
346
|
+
sort?: Record<string, 1 | -1>; // 排序配置
|
|
347
|
+
limit?: number; // 限制返回数量
|
|
348
|
+
skip?: number; // 跳过数量
|
|
349
|
+
maxTimeMS?: number; // 查询超时时间(毫秒)
|
|
350
|
+
hint?: any; // 索引提示
|
|
351
|
+
collation?: any; // 排序规则
|
|
352
|
+
verbosity?: 'queryPlanner' | 'executionStats' | 'allPlansExecution'; // 详细程度(默认 'queryPlanner')
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Bookmark 维护 APIs 相关接口
|
|
356
|
+
interface BookmarkKeyDims {
|
|
357
|
+
sort?: Record<string, 1 | -1>; // 排序配置(与 findPage 一致)
|
|
358
|
+
limit?: number; // 每页数量
|
|
359
|
+
query?: object; // 查询条件(用于计算 queryShape)
|
|
360
|
+
pipeline?: object[]; // 聚合管道(用于计算 pipelineShape)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
interface PrewarmBookmarksResult {
|
|
364
|
+
warmed: number; // 成功预热的 bookmark 数量
|
|
365
|
+
failed: number; // 预热失败的 bookmark 数量
|
|
366
|
+
keys: string[]; // 已缓存的 bookmark 键列表
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
interface ListBookmarksResult {
|
|
370
|
+
count: number; // bookmark 总数
|
|
371
|
+
pages: number[]; // 已缓存的页码列表(排序后)
|
|
372
|
+
keys: string[]; // 缓存键列表
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
interface ClearBookmarksResult {
|
|
376
|
+
cleared: number; // 清除的 bookmark 数量
|
|
377
|
+
pattern: string; // 使用的匹配模式
|
|
378
|
+
keysBefore: number; // 清除前的 bookmark 数量
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// 跳页相关类型
|
|
382
|
+
interface JumpOptions {
|
|
383
|
+
step?: number; // 书签密度:每隔 step 页存一个书签;默认 10
|
|
384
|
+
maxHops?: number; // 单次跳页允许的"连续 after 次数(累计)"上限;默认 20
|
|
385
|
+
keyDims?: object; // 可选;未传则自动生成去敏形状
|
|
386
|
+
getBookmark?: (params: { keyDims: any; page: number }) => Promise<string | null>;
|
|
387
|
+
saveBookmark?: (params: { keyDims: any; page: number; cursor: string; ttlMs?: number }) => Promise<void>;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
interface OffsetJumpOptions {
|
|
391
|
+
enable?: boolean; // 开启后,当 skip=(page-1)*limit ≤ maxSkip 时走 `$skip+$limit`
|
|
392
|
+
maxSkip?: number; // 默认 50_000;超过则回退到"书签跳转"逻辑
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
interface TotalsOptions {
|
|
396
|
+
mode?: 'none' | 'async' | 'approx' | 'sync'; // 默认 'none'
|
|
397
|
+
maxTimeMS?: number; // 用于 `countDocuments` 的超时(sync/async)
|
|
398
|
+
ttlMs?: number; // 总数缓存 TTL(async/approx),默认 10 分钟
|
|
399
|
+
hint?: any; // 计数 hint(可选)
|
|
400
|
+
collation?: any; // 计数 collation(可选,与列表一致更安全)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
interface MetaOptions {
|
|
404
|
+
level?: 'op' | 'sub'; // sub: 返回子步骤耗时(仅 findPage)
|
|
405
|
+
includeCache?: boolean; // 包含缓存相关信息
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 深度分页(统一版)选项与返回类型
|
|
409
|
+
interface FindPageOptions extends FindOptions {
|
|
410
|
+
pipeline?: object[];
|
|
411
|
+
after?: string;
|
|
412
|
+
before?: string;
|
|
413
|
+
limit: number;
|
|
414
|
+
allowDiskUse?: boolean;
|
|
415
|
+
/** Mongo-only: 透传 hint 到 aggregate */
|
|
416
|
+
hint?: any;
|
|
417
|
+
/** Mongo-only: 透传 collation 到 aggregate */
|
|
418
|
+
collation?: any;
|
|
419
|
+
|
|
420
|
+
// 新增:跳页相关参数
|
|
421
|
+
page?: number; // 目标页(≥1);与 after/before 互斥
|
|
422
|
+
jump?: JumpOptions; // 跳页(书签)配置
|
|
423
|
+
offsetJump?: OffsetJumpOptions; // 小范围 offset 兜底
|
|
424
|
+
totals?: TotalsOptions; // 总数/总页数配置
|
|
425
|
+
meta?: boolean | MetaOptions; // 返回耗时元信息
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
interface MetaInfo {
|
|
429
|
+
op: string;
|
|
430
|
+
ns: { iid: string; type: string; db: string; coll: string };
|
|
431
|
+
startTs: number;
|
|
432
|
+
endTs: number;
|
|
433
|
+
durationMs: number;
|
|
434
|
+
maxTimeMS?: number;
|
|
435
|
+
fromCache?: boolean;
|
|
436
|
+
cacheHit?: boolean;
|
|
437
|
+
cacheTtl?: number;
|
|
438
|
+
keyHash?: string;
|
|
439
|
+
// findPage 专用字段
|
|
440
|
+
page?: number;
|
|
441
|
+
after?: boolean;
|
|
442
|
+
before?: boolean;
|
|
443
|
+
hops?: number;
|
|
444
|
+
step?: number;
|
|
445
|
+
steps?: Array<{ phase: 'hop' | 'offset'; index?: number; durationMs: number }>; // level='sub' 时提供
|
|
446
|
+
error?: { code?: string; message: string };
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
interface TotalsInfo {
|
|
450
|
+
mode: 'async' | 'sync' | 'approx';
|
|
451
|
+
total?: number | null | undefined; // async: null(未就绪);approx: undefined(未知或近似)
|
|
452
|
+
totalPages?: number | null | undefined;
|
|
453
|
+
token?: string; // async 时返回的短标识(<keyHash>)
|
|
454
|
+
ts?: number; // 写入时间戳(毫秒),如果来自缓存
|
|
455
|
+
error?: string; // 仅 async:统计失败时可能附带的错误标识
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
interface PageInfo {
|
|
459
|
+
hasNext: boolean;
|
|
460
|
+
hasPrev: boolean;
|
|
461
|
+
startCursor: string | null;
|
|
462
|
+
endCursor: string | null;
|
|
463
|
+
currentPage?: number; // 仅跳页/offset 模式回显目标页号(逻辑页号)
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
interface PageResult<T = any> {
|
|
467
|
+
items: T[];
|
|
468
|
+
pageInfo: PageInfo;
|
|
469
|
+
totals?: TotalsInfo; // 当启用 totals 时返回
|
|
470
|
+
meta?: MetaInfo; // 当启用 meta 时返回
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// 带 meta 的返回类型(用于 findOne/find/count)
|
|
474
|
+
interface ResultWithMeta<T = any> {
|
|
475
|
+
data: T;
|
|
476
|
+
meta: MetaInfo;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
interface HealthView {
|
|
480
|
+
status: 'up' | 'down';
|
|
481
|
+
connected: boolean;
|
|
482
|
+
defaults?: any;
|
|
483
|
+
cache?: any;
|
|
484
|
+
driver?: { connected: boolean };
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
interface CollectionAccessor {
|
|
488
|
+
getNamespace(): { iid: string; type: string; db: string; collection: string };
|
|
489
|
+
dropCollection(): Promise<boolean>;
|
|
490
|
+
createCollection(name?: string | null, options?: any): Promise<boolean>;
|
|
491
|
+
createView(viewName: string, source: string, pipeline?: any[]): Promise<boolean>;
|
|
492
|
+
|
|
493
|
+
// findOne 重载:支持 meta 参数
|
|
494
|
+
findOne(query?: any, options?: Omit<FindOptions, 'meta'>): Promise<any | null>;
|
|
495
|
+
findOne(query: any, options: FindOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<any | null>>;
|
|
496
|
+
findOne(query?: any, options?: FindOptions): Promise<any | null | ResultWithMeta<any | null>>;
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* 通过 _id 查询单个文档(便利方法)
|
|
500
|
+
* @param id - 文档的 _id(字符串会自动转换为 ObjectId)
|
|
501
|
+
* @param options - 查询选项(支持 projection, cache, maxTimeMS, comment)
|
|
502
|
+
* @returns Promise<文档 | null>
|
|
503
|
+
* @throws {Error} 当 id 参数无效时
|
|
504
|
+
* @example
|
|
505
|
+
* // 字符串 ID(自动转换)
|
|
506
|
+
* const user = await collection('users').findOneById('507f1f77bcf86cd799439011');
|
|
507
|
+
*
|
|
508
|
+
* @example
|
|
509
|
+
* // ObjectId
|
|
510
|
+
* const user = await collection('users').findOneById(new ObjectId(userId));
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* // 带选项
|
|
514
|
+
* const user = await collection('users').findOneById(userId, {
|
|
515
|
+
* projection: { name: 1, email: 1 },
|
|
516
|
+
* cache: 5000
|
|
517
|
+
* });
|
|
518
|
+
*/
|
|
519
|
+
findOneById(id: string | any, options?: Omit<FindOptions, 'meta'>): Promise<any | null>;
|
|
520
|
+
|
|
521
|
+
u /**
|
|
522
|
+
* 批量通过 _id 查询多个文档(便利方法)
|
|
523
|
+
* @param ids - _id 数组(支持字符串和 ObjectId 混合)
|
|
524
|
+
* @param options - 查询选项
|
|
525
|
+
* @returns Promise<文档数组>
|
|
526
|
+
* @throws {Error} 当 ids 参数无效时
|
|
527
|
+
* @example
|
|
528
|
+
* // 字符串 ID 数组
|
|
529
|
+
* const users = await collection('users').findByIds([
|
|
530
|
+
* '507f1f77bcf86cd799439011',
|
|
531
|
+
* '507f1f77bcf86cd799439012'
|
|
532
|
+
* ]);
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* // ObjectId 数组
|
|
536
|
+
* const users = await collection('users').findByIds([
|
|
537
|
+
* new ObjectId('507f1f77bcf86cd799439011'),
|
|
538
|
+
* new ObjectId('507f1f77bcf86cd799439012')
|
|
539
|
+
* ]);
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* // 混合类型 + 选项
|
|
543
|
+
* const users = await collection('users').findByIds(
|
|
544
|
+
* ['507f1f77bcf86cd799439011', new ObjectId('507f1f77bcf86cd799439012')],
|
|
545
|
+
* {
|
|
546
|
+
* projection: { name: 1, email: 1 },
|
|
547
|
+
* sort: { name: 1 },
|
|
548
|
+
* cache: 5000,
|
|
549
|
+
* preserveOrder: true
|
|
550
|
+
* }
|
|
551
|
+
* );
|
|
552
|
+
*/
|
|
553
|
+
findByIds(
|
|
554
|
+
ids: Array<string | any>,
|
|
555
|
+
options?: {
|
|
556
|
+
projection?: Record<string, any>;
|
|
557
|
+
sort?: Record<string, 1 | -1>;
|
|
558
|
+
cache?: number;
|
|
559
|
+
maxTimeMS?: number;
|
|
560
|
+
comment?: string;
|
|
561
|
+
preserveOrder?: boolean;
|
|
562
|
+
}
|
|
563
|
+
): Promise<any[]>;
|
|
564
|
+
|
|
565
|
+
// find 重载:支持 meta 参数和链式调用 (v2.0+)
|
|
566
|
+
find<T = any>(query?: any): FindChain<T>;
|
|
567
|
+
find<T = any>(query: any, options: FindOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
|
|
568
|
+
find<T = any>(query?: any, options?: FindOptions): Promise<T[]> | FindChain<T> | ResultWithMeta<T[]>;
|
|
569
|
+
|
|
570
|
+
// count 重载:支持 meta 参数
|
|
571
|
+
count(query?: any, options?: Omit<CountOptions, 'meta'>): Promise<number>;
|
|
572
|
+
count(query: any, options: CountOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<number>>;
|
|
573
|
+
count(query?: any, options?: CountOptions): Promise<number | ResultWithMeta<number>>;
|
|
574
|
+
|
|
575
|
+
// aggregate 重载:支持 meta 参数和链式调用 (v2.0+)
|
|
576
|
+
aggregate<T = any>(pipeline?: any[]): AggregateChain<T>;
|
|
577
|
+
aggregate<T = any>(pipeline: any[], options: AggregateOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
|
|
578
|
+
aggregate<T = any>(pipeline?: any[], options?: AggregateOptions): Promise<T[]> | AggregateChain<T> | ResultWithMeta<T[]>;
|
|
579
|
+
|
|
580
|
+
// distinct 重载:支持 meta 参数
|
|
581
|
+
distinct<T = any>(field: string, query?: any, options?: Omit<DistinctOptions, 'meta'>): Promise<T[]>;
|
|
582
|
+
distinct<T = any>(field: string, query: any, options: DistinctOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
|
|
583
|
+
distinct<T = any>(field: string, query?: any, options?: DistinctOptions): Promise<T[] | ResultWithMeta<T[]>>;
|
|
584
|
+
|
|
585
|
+
// stream:返回 Node.js 可读流
|
|
586
|
+
stream(query?: any, options?: StreamOptions): NodeJS.ReadableStream;
|
|
587
|
+
|
|
588
|
+
// explain:查询执行计划诊断
|
|
589
|
+
explain(query?: any, options?: ExplainOptions): Promise<any>;
|
|
590
|
+
|
|
591
|
+
// Bookmark 维护 APIs
|
|
592
|
+
prewarmBookmarks(keyDims: BookmarkKeyDims, pages: number[]): Promise<PrewarmBookmarksResult>;
|
|
593
|
+
listBookmarks(keyDims?: BookmarkKeyDims): Promise<ListBookmarksResult>;
|
|
594
|
+
clearBookmarks(keyDims?: BookmarkKeyDims): Promise<ClearBookmarksResult>;
|
|
595
|
+
|
|
596
|
+
// findPage:已在 PageResult 中包含 meta 字段,无需重载
|
|
597
|
+
findPage(options: FindPageOptions): Promise<PageResult>;
|
|
598
|
+
|
|
599
|
+
// 写入操作
|
|
600
|
+
insertOne(options: InsertOneOptions): Promise<InsertOneResult>;
|
|
601
|
+
insertMany(options: InsertManyOptions): Promise<InsertManyResult>;
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Upsert 单个文档(存在则更新,不存在则插入)- 便利方法
|
|
605
|
+
* @param filter - 查询条件
|
|
606
|
+
* @param update - 更新内容(直接字段或操作符)
|
|
607
|
+
* @param options - 操作选项
|
|
608
|
+
* @returns Promise<UpsertOneResult>
|
|
609
|
+
* @example
|
|
610
|
+
* // 基础用法(自动包装 $set)
|
|
611
|
+
* const result = await collection('users').upsertOne(
|
|
612
|
+
* { userId: 'user123' },
|
|
613
|
+
* { name: 'Alice', age: 30 }
|
|
614
|
+
* );
|
|
615
|
+
*
|
|
616
|
+
* @example
|
|
617
|
+
* // 使用更新操作符
|
|
618
|
+
* const result = await collection('users').upsertOne(
|
|
619
|
+
* { userId: 'user123' },
|
|
620
|
+
* { $set: { name: 'Alice' }, $inc: { count: 1 } }
|
|
621
|
+
* );
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* // 带选项
|
|
625
|
+
* const result = await collection('configs').upsertOne(
|
|
626
|
+
* { key: 'theme' },
|
|
627
|
+
* { value: 'dark' },
|
|
628
|
+
* { maxTimeMS: 5000, comment: 'sync-config' }
|
|
629
|
+
* );
|
|
630
|
+
*/
|
|
631
|
+
upsertOne(
|
|
632
|
+
filter: Record<string, any>,
|
|
633
|
+
update: Record<string, any>,
|
|
634
|
+
options?: {
|
|
635
|
+
maxTimeMS?: number;
|
|
636
|
+
comment?: string;
|
|
637
|
+
}
|
|
638
|
+
): Promise<{
|
|
639
|
+
acknowledged: boolean;
|
|
640
|
+
matchedCount: number;
|
|
641
|
+
modifiedCount: number;
|
|
642
|
+
upsertedId?: any;
|
|
643
|
+
upsertedCount: number;
|
|
644
|
+
}>;
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* 原子递增/递减字段值(便利方法)
|
|
648
|
+
* @param filter - 查询条件
|
|
649
|
+
* @param field - 字段名或字段-增量对象
|
|
650
|
+
* @param increment - 增量(默认 1,负数为递减)
|
|
651
|
+
* @param options - 操作选项
|
|
652
|
+
* @returns Promise<IncrementOneResult>
|
|
653
|
+
*/
|
|
654
|
+
incrementOne(
|
|
655
|
+
filter: Record<string, any>,
|
|
656
|
+
field: string | Record<string, number>,
|
|
657
|
+
increment?: number,
|
|
658
|
+
options?: {
|
|
659
|
+
returnDocument?: 'before' | 'after';
|
|
660
|
+
projection?: Record<string, any>;
|
|
661
|
+
maxTimeMS?: number;
|
|
662
|
+
comment?: string;
|
|
663
|
+
}
|
|
664
|
+
): Promise<{
|
|
665
|
+
acknowledged: boolean;
|
|
666
|
+
matchedCount: number;
|
|
667
|
+
modifiedCount: number;
|
|
668
|
+
value: any | null;
|
|
669
|
+
}>;
|
|
670
|
+
|
|
671
|
+
invalidate(op?: 'find' | 'findOne' | 'count' | 'findPage' | 'aggregate' | 'distinct'): Promise<number>;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
type DbAccessor = {
|
|
675
|
+
collection: (name: string) => CollectionAccessor;
|
|
676
|
+
db: (dbName: string) => { collection: (name: string) => CollectionAccessor };
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
export default class MonSQLize {
|
|
680
|
+
constructor(options: BaseOptions);
|
|
681
|
+
connect(): Promise<DbAccessor>;
|
|
682
|
+
getCache(): CacheLike;
|
|
683
|
+
getDefaults(): { maxTimeMS?: number; findLimit?: number; namespace?: { instanceId?: string; scope?: 'database' | 'connection' }; slowQueryMs?: number };
|
|
684
|
+
close(): Promise<void>;
|
|
685
|
+
|
|
686
|
+
/** 事件订阅:connected/closed/error/slow-query/query */
|
|
687
|
+
on(event: 'connected', handler: (payload: { type: string; db: string; scope?: string; iid?: string }) => void): void;
|
|
688
|
+
on(event: 'closed', handler: (payload: { type: string; db: string; iid?: string }) => void): void;
|
|
689
|
+
on(event: 'error', handler: (payload: { type: string; db: string; error: string; iid?: string }) => void): void;
|
|
690
|
+
on(event: 'slow-query', handler: (meta: MetaInfo) => void): void;
|
|
691
|
+
on(event: 'query', handler: (meta: MetaInfo) => void): void;
|
|
692
|
+
on(event: string, handler: (payload: any) => void): void;
|
|
693
|
+
|
|
694
|
+
/** 一次性事件订阅 */
|
|
695
|
+
once(event: 'connected', handler: (payload: { type: string; db: string; scope?: string; iid?: string }) => void): void;
|
|
696
|
+
once(event: 'closed', handler: (payload: { type: string; db: string; iid?: string }) => void): void;
|
|
697
|
+
once(event: 'error', handler: (payload: { type: string; db: string; error: string; iid?: string }) => void): void;
|
|
698
|
+
once(event: 'slow-query', handler: (meta: MetaInfo) => void): void;
|
|
699
|
+
once(event: 'query', handler: (meta: MetaInfo) => void): void;
|
|
700
|
+
once(event: string, handler: (payload: any) => void): void;
|
|
701
|
+
|
|
702
|
+
/** 取消事件订阅 */
|
|
703
|
+
off(event: 'connected', handler: (payload: { type: string; db: string; scope?: string; iid?: string }) => void): void;
|
|
704
|
+
off(event: 'closed', handler: (payload: { type: string; db: string; iid?: string }) => void): void;
|
|
705
|
+
off(event: 'error', handler: (payload: { type: string; db: string; error: string; iid?: string }) => void): void;
|
|
706
|
+
off(event: 'slow-query', handler: (meta: MetaInfo) => void): void;
|
|
707
|
+
off(event: 'query', handler: (meta: MetaInfo) => void): void;
|
|
708
|
+
off(event: string, handler: (payload: any) => void): void;
|
|
709
|
+
|
|
710
|
+
/** 触发事件 */
|
|
711
|
+
emit(event: string, payload: any): void;
|
|
712
|
+
|
|
713
|
+
/** 健康检查 */
|
|
714
|
+
health(): Promise<HealthView>;
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* 创建手动事务会话
|
|
718
|
+
* @param options - 事务选项
|
|
719
|
+
* @returns Transaction 实例
|
|
720
|
+
* @since v0.2.0
|
|
721
|
+
* @example
|
|
722
|
+
* const tx = await msq.startTransaction();
|
|
723
|
+
* try {
|
|
724
|
+
* await collection('users').updateOne({...}, {...}, { session: tx.session });
|
|
725
|
+
* await tx.commit();
|
|
726
|
+
* } catch (error) {
|
|
727
|
+
* await tx.abort();
|
|
728
|
+
* }
|
|
729
|
+
*/
|
|
730
|
+
startTransaction(options?: TransactionOptions): Promise<Transaction>;
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* 自动管理事务生命周期(推荐)
|
|
734
|
+
* @param callback - 事务回调函数
|
|
735
|
+
* @param options - 事务选项
|
|
736
|
+
* @returns 回调函数的返回值
|
|
737
|
+
* @since v0.2.0
|
|
738
|
+
* @example
|
|
739
|
+
* await msq.withTransaction(async (tx) => {
|
|
740
|
+
* await collection('accounts').updateOne({ _id: 'A' }, { $inc: { balance: -100 } }, { session: tx.session });
|
|
741
|
+
* await collection('accounts').updateOne({ _id: 'B' }, { $inc: { balance: 100 } }, { session: tx.session });
|
|
742
|
+
* });
|
|
743
|
+
*/
|
|
744
|
+
withTransaction<T = any>(
|
|
745
|
+
callback: (transaction: Transaction) => Promise<T>,
|
|
746
|
+
options?: TransactionOptions
|
|
747
|
+
): Promise<T>;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// ============================================================================
|
|
751
|
+
// 链式调用 API (v2.0+)
|
|
752
|
+
// ============================================================================
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Collation 选项(字符串排序规则)
|
|
756
|
+
*/
|
|
757
|
+
interface CollationOptions {
|
|
758
|
+
locale: string; // 语言代码,如 'zh', 'en'
|
|
759
|
+
strength?: number; // 比较级别:1=基本, 2=重音, 3=大小写
|
|
760
|
+
caseLevel?: boolean; // 是否区分大小写
|
|
761
|
+
caseFirst?: 'upper' | 'lower'; // 大小写优先级
|
|
762
|
+
numericOrdering?: boolean; // 数字排序
|
|
763
|
+
alternate?: 'non-ignorable' | 'shifted'; // 空格和标点处理
|
|
764
|
+
maxVariable?: 'punct' | 'space'; // 最大可变字符
|
|
765
|
+
backwards?: boolean; // 反向比较
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Explain 执行计划结果
|
|
770
|
+
*/
|
|
771
|
+
interface ExplainResult {
|
|
772
|
+
queryPlanner: {
|
|
773
|
+
plannerVersion: number;
|
|
774
|
+
namespace: string;
|
|
775
|
+
indexFilterSet: boolean;
|
|
776
|
+
parsedQuery?: any;
|
|
777
|
+
winningPlan: any;
|
|
778
|
+
rejectedPlans: any[];
|
|
779
|
+
};
|
|
780
|
+
executionStats?: {
|
|
781
|
+
executionSuccess: boolean;
|
|
782
|
+
nReturned: number;
|
|
783
|
+
executionTimeMillis: number;
|
|
784
|
+
totalKeysExamined: number;
|
|
785
|
+
totalDocsExamined: number;
|
|
786
|
+
executionStages: any;
|
|
787
|
+
allPlansExecution?: any[];
|
|
788
|
+
};
|
|
789
|
+
serverInfo?: {
|
|
790
|
+
host: string;
|
|
791
|
+
port: number;
|
|
792
|
+
version: string;
|
|
793
|
+
gitVersion: string;
|
|
794
|
+
};
|
|
795
|
+
ok: number;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* FindChain - find 查询的链式调用构建器
|
|
800
|
+
*
|
|
801
|
+
* @template T - 文档类型
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* // 基础链式调用
|
|
805
|
+
* const results = await collection<Product>('products')
|
|
806
|
+
* .find({ category: 'electronics' })
|
|
807
|
+
* .limit(10)
|
|
808
|
+
* .skip(5)
|
|
809
|
+
* .sort({ price: -1 });
|
|
810
|
+
*
|
|
811
|
+
* @example
|
|
812
|
+
* // 复杂链式调用
|
|
813
|
+
* const results = await collection<Product>('products')
|
|
814
|
+
* .find({ inStock: true })
|
|
815
|
+
* .sort({ rating: -1 })
|
|
816
|
+
* .skip(10)
|
|
817
|
+
* .limit(20)
|
|
818
|
+
* .project({ name: 1, price: 1 })
|
|
819
|
+
* .hint({ category: 1, price: -1 })
|
|
820
|
+
* .maxTimeMS(5000);
|
|
821
|
+
*/
|
|
822
|
+
interface FindChain<T = any> extends PromiseLike<T[]> {
|
|
823
|
+
/**
|
|
824
|
+
* 限制返回文档数量
|
|
825
|
+
* @param n - 限制数量,必须为非负数
|
|
826
|
+
* @returns 返回自身以支持链式调用
|
|
827
|
+
* @throws {Error} 如果 n 不是非负数
|
|
828
|
+
*/
|
|
829
|
+
limit(n: number): FindChain<T>;
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* 跳过指定数量的文档
|
|
833
|
+
* @param n - 跳过数量,必须为非负数
|
|
834
|
+
* @returns 返回自身以支持链式调用
|
|
835
|
+
* @throws {Error} 如果 n 不是非负数
|
|
836
|
+
*/
|
|
837
|
+
skip(n: number): FindChain<T>;
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* 设置排序规则
|
|
841
|
+
* @param spec - 排序配置,如 { price: -1, name: 1 }
|
|
842
|
+
* @returns 返回自身以支持链式调用
|
|
843
|
+
* @throws {Error} 如果 spec 不是对象或数组
|
|
844
|
+
*/
|
|
845
|
+
sort(spec: Record<string, 1 | -1> | Array<[string, 1 | -1]>): FindChain<T>;
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* 设置字段投影
|
|
849
|
+
* @param spec - 投影配置,如 { name: 1, price: 1 }
|
|
850
|
+
* @returns 返回带有投影类型的新链
|
|
851
|
+
* @throws {Error} 如果 spec 不是对象或数组
|
|
852
|
+
*/
|
|
853
|
+
project<K extends keyof T>(spec: Record<K, 1 | 0> | Array<K>): FindChain<Pick<T, K>>;
|
|
854
|
+
project(spec: Record<string, 1 | 0> | string[]): FindChain<Partial<T>>;
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* 设置索引提示(强制使用指定索引)
|
|
858
|
+
* @param spec - 索引名称或索引规格
|
|
859
|
+
* @returns 返回自身以支持链式调用
|
|
860
|
+
* @throws {Error} 如果 spec 为空
|
|
861
|
+
*/
|
|
862
|
+
hint(spec: Record<string, 1 | -1> | string): FindChain<T>;
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* 设置排序规则(用于字符串排序)
|
|
866
|
+
* @param spec - 排序规则配置
|
|
867
|
+
* @returns 返回自身以支持链式调用
|
|
868
|
+
* @throws {Error} 如果 spec 不是对象
|
|
869
|
+
*/
|
|
870
|
+
collation(spec: CollationOptions): FindChain<T>;
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* 设置查询注释(用于日志追踪)
|
|
874
|
+
* @param str - 注释内容
|
|
875
|
+
* @returns 返回自身以支持链式调用
|
|
876
|
+
* @throws {Error} 如果 str 不是字符串
|
|
877
|
+
*/
|
|
878
|
+
comment(str: string): FindChain<T>;
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* 设置查询超时时间
|
|
882
|
+
* @param ms - 超时时间(毫秒)
|
|
883
|
+
* @returns 返回自身以支持链式调用
|
|
884
|
+
* @throws {Error} 如果 ms 不是非负数
|
|
885
|
+
*/
|
|
886
|
+
maxTimeMS(ms: number): FindChain<T>;
|
|
887
|
+
|
|
888
|
+
/**
|
|
889
|
+
* 设置批处理大小
|
|
890
|
+
* @param n - 批处理大小
|
|
891
|
+
* @returns 返回自身以支持链式调用
|
|
892
|
+
* @throws {Error} 如果 n 不是非负数
|
|
893
|
+
*/
|
|
894
|
+
batchSize(n: number): FindChain<T>;
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* 返回查询执行计划(不执行查询)
|
|
898
|
+
* @param verbosity - 详细级别
|
|
899
|
+
* @returns 执行计划
|
|
900
|
+
*/
|
|
901
|
+
explain(verbosity?: 'queryPlanner' | 'executionStats' | 'allPlansExecution'): Promise<ExplainResult>;
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* 返回流式结果
|
|
905
|
+
* @returns MongoDB 游标流
|
|
906
|
+
*/
|
|
907
|
+
stream(): NodeJS.ReadableStream;
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* 显式转换为数组(执行查询)
|
|
911
|
+
* @returns 查询结果数组
|
|
912
|
+
* @throws {Error} 如果查询已执行
|
|
913
|
+
*/
|
|
914
|
+
toArray(): Promise<T[]>;
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Promise.then 接口
|
|
918
|
+
*/
|
|
919
|
+
then<TResult1 = T[], TResult2 = never>(
|
|
920
|
+
onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null,
|
|
921
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
922
|
+
): Promise<TResult1 | TResult2>;
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Promise.catch 接口
|
|
926
|
+
*/
|
|
927
|
+
catch<TResult = never>(
|
|
928
|
+
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
929
|
+
): Promise<T[] | TResult>;
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Promise.finally 接口
|
|
933
|
+
*/
|
|
934
|
+
finally(onfinally?: (() => void) | null): Promise<T[]>;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* AggregateChain - aggregate 查询的链式调用构建器
|
|
939
|
+
*
|
|
940
|
+
* @template T - 文档类型
|
|
941
|
+
*
|
|
942
|
+
* @example
|
|
943
|
+
* // 基础聚合
|
|
944
|
+
* const results = await collection<Order>('orders')
|
|
945
|
+
* .aggregate([
|
|
946
|
+
* { $match: { status: 'paid' } },
|
|
947
|
+
* { $group: { _id: '$category', total: { $sum: '$amount' } } }
|
|
948
|
+
* ])
|
|
949
|
+
* .allowDiskUse(true);
|
|
950
|
+
*
|
|
951
|
+
* @example
|
|
952
|
+
* // 复杂聚合
|
|
953
|
+
* const results = await collection<Order>('orders')
|
|
954
|
+
* .aggregate([
|
|
955
|
+
* { $match: { status: 'paid' } },
|
|
956
|
+
* { $sort: { createdAt: -1 } },
|
|
957
|
+
* { $limit: 100 }
|
|
958
|
+
* ])
|
|
959
|
+
* .hint({ status: 1, createdAt: -1 })
|
|
960
|
+
* .allowDiskUse(true)
|
|
961
|
+
* .maxTimeMS(10000);
|
|
962
|
+
*/
|
|
963
|
+
interface AggregateChain<T = any> extends PromiseLike<T[]> {
|
|
964
|
+
/**
|
|
965
|
+
* 设置索引提示(强制使用指定索引)
|
|
966
|
+
* @param spec - 索引名称或索引规格
|
|
967
|
+
* @returns 返回自身以支持链式调用
|
|
968
|
+
* @throws {Error} 如果 spec 为空
|
|
969
|
+
*/
|
|
970
|
+
hint(spec: Record<string, 1 | -1> | string): AggregateChain<T>;
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* 设置排序规则(用于字符串排序)
|
|
974
|
+
* @param spec - 排序规则配置
|
|
975
|
+
* @returns 返回自身以支持链式调用
|
|
976
|
+
* @throws {Error} 如果 spec 不是对象
|
|
977
|
+
*/
|
|
978
|
+
collation(spec: CollationOptions): AggregateChain<T>;
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* 设置查询注释(用于日志追踪)
|
|
982
|
+
* @param str - 注释内容
|
|
983
|
+
* @returns 返回自身以支持链式调用
|
|
984
|
+
* @throws {Error} 如果 str 不是字符串
|
|
985
|
+
*/
|
|
986
|
+
comment(str: string): AggregateChain<T>;
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* 设置查询超时时间
|
|
990
|
+
* @param ms - 超时时间(毫秒)
|
|
991
|
+
* @returns 返回自身以支持链式调用
|
|
992
|
+
* @throws {Error} 如果 ms 不是非负数
|
|
993
|
+
*/
|
|
994
|
+
maxTimeMS(ms: number): AggregateChain<T>;
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* 允许使用磁盘进行大数据量排序/分组
|
|
998
|
+
* @param bool - 是否允许
|
|
999
|
+
* @returns 返回自身以支持链式调用
|
|
1000
|
+
* @throws {Error} 如果 bool 不是布尔值
|
|
1001
|
+
*/
|
|
1002
|
+
allowDiskUse(bool: boolean): AggregateChain<T>;
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* 设置批处理大小
|
|
1006
|
+
* @param n - 批处理大小
|
|
1007
|
+
* @returns 返回自身以支持链式调用
|
|
1008
|
+
* @throws {Error} 如果 n 不是非负数
|
|
1009
|
+
*/
|
|
1010
|
+
batchSize(n: number): AggregateChain<T>;
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* 返回聚合执行计划(不执行聚合)
|
|
1014
|
+
* @param verbosity - 详细级别
|
|
1015
|
+
* @returns 执行计划
|
|
1016
|
+
*/
|
|
1017
|
+
explain(verbosity?: 'queryPlanner' | 'executionStats' | 'allPlansExecution'): Promise<ExplainResult>;
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* 返回流式结果
|
|
1021
|
+
* @returns MongoDB 游标流
|
|
1022
|
+
*/
|
|
1023
|
+
stream(): NodeJS.ReadableStream;
|
|
1024
|
+
|
|
1025
|
+
/**
|
|
1026
|
+
* 显式转换为数组(执行聚合)
|
|
1027
|
+
* @returns 聚合结果数组
|
|
1028
|
+
* @throws {Error} 如果查询已执行
|
|
1029
|
+
*/
|
|
1030
|
+
toArray(): Promise<T[]>;
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Promise.then 接口
|
|
1034
|
+
*/
|
|
1035
|
+
then<TResult1 = T[], TResult2 = never>(
|
|
1036
|
+
onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null,
|
|
1037
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
1038
|
+
): Promise<TResult1 | TResult2>;
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* Promise.catch 接口
|
|
1042
|
+
*/
|
|
1043
|
+
catch<TResult = never>(
|
|
1044
|
+
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
1045
|
+
): Promise<T[] | TResult>;
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Promise.finally 接口
|
|
1049
|
+
*/
|
|
1050
|
+
finally(onfinally?: (() => void) | null): Promise<T[]>;
|
|
1051
|
+
}
|
|
1052
|
+
}
|