@cloudbase/database 0.10.0 → 0.12.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/dist/commonjs/transaction/query.d.ts +39 -1
- package/dist/commonjs/transaction/query.js +251 -1
- package/dist/esm/transaction/query.d.ts +39 -1
- package/dist/esm/transaction/query.js +251 -1
- package/package.json +2 -2
- package/src/transaction/query.ts +355 -2
- package/tests/transaction-query.test.ts +657 -0
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -101
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -210
- package/coverage/lcov.info +0 -0
- package/dist/esm/aggregate.d.ts.map +0 -1
- package/dist/esm/collection.d.ts.map +0 -1
- package/dist/esm/command.d.ts.map +0 -1
- package/dist/esm/commands/logic.d.ts.map +0 -1
- package/dist/esm/commands/query.d.ts.map +0 -1
- package/dist/esm/commands/update.d.ts.map +0 -1
- package/dist/esm/config/app.config.d.ts.map +0 -1
- package/dist/esm/config/error.config.d.ts.map +0 -1
- package/dist/esm/const/code.d.ts.map +0 -1
- package/dist/esm/constant.d.ts.map +0 -1
- package/dist/esm/document.d.ts.map +0 -1
- package/dist/esm/geo/index.d.ts.map +0 -1
- package/dist/esm/geo/interface.d.ts.map +0 -1
- package/dist/esm/geo/lineString.d.ts.map +0 -1
- package/dist/esm/geo/multiLineString.d.ts.map +0 -1
- package/dist/esm/geo/multiPoint.d.ts.map +0 -1
- package/dist/esm/geo/multiPolygon.d.ts.map +0 -1
- package/dist/esm/geo/point.d.ts.map +0 -1
- package/dist/esm/geo/polygon.d.ts.map +0 -1
- package/dist/esm/helper/symbol.d.ts.map +0 -1
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/lib/util.d.ts.map +0 -1
- package/dist/esm/operator-map.d.ts.map +0 -1
- package/dist/esm/query.d.ts.map +0 -1
- package/dist/esm/regexp/index.d.ts.map +0 -1
- package/dist/esm/serializer/common.d.ts.map +0 -1
- package/dist/esm/serializer/datatype.d.ts.map +0 -1
- package/dist/esm/serializer/query.d.ts.map +0 -1
- package/dist/esm/serializer/update.d.ts.map +0 -1
- package/dist/esm/serverDate/index.d.ts.map +0 -1
- package/dist/esm/transaction/collection.d.ts.map +0 -1
- package/dist/esm/transaction/document.d.ts.map +0 -1
- package/dist/esm/transaction/index.d.ts.map +0 -1
- package/dist/esm/transaction/query.d.ts.map +0 -1
- package/dist/esm/typings/index.d.ts.map +0 -1
- package/dist/esm/typings/realtime.d.ts.map +0 -1
- package/dist/esm/util.d.ts.map +0 -1
- package/dist/esm/utils/error.d.ts.map +0 -1
- package/dist/esm/utils/msg.d.ts.map +0 -1
- package/dist/esm/utils/symbol.d.ts.map +0 -1
- package/dist/esm/utils/type.d.ts.map +0 -1
- package/dist/esm/utils/utils.d.ts.map +0 -1
- package/dist/esm/validate.d.ts.map +0 -1
package/src/transaction/query.ts
CHANGED
|
@@ -1,8 +1,59 @@
|
|
|
1
1
|
import { Transaction } from './index'
|
|
2
|
+
import { EJSON } from 'bson'
|
|
3
|
+
import { OrderByDirection, ErrorCode } from '../constant'
|
|
4
|
+
import { Validate } from '../validate'
|
|
5
|
+
import { QuerySerializer } from '../serializer/query'
|
|
6
|
+
import { UpdateSerializer } from '../serializer/update'
|
|
7
|
+
import { Util } from '../util'
|
|
8
|
+
|
|
9
|
+
const GET_DOC = 'database.getInTransaction'
|
|
10
|
+
const UPDATE_DOC = 'database.updateDocInTransaction'
|
|
11
|
+
const DELETE_DOC = 'database.deleteDocInTransaction'
|
|
12
|
+
|
|
13
|
+
interface QueryOrder {
|
|
14
|
+
field?: string
|
|
15
|
+
direction?: 'asc' | 'desc'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface QueryOption {
|
|
19
|
+
limit?: number
|
|
20
|
+
offset?: number
|
|
21
|
+
projection?: Object
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface TransactionAPI {
|
|
25
|
+
send(interfaceName: string, param?: any)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface GetResult {
|
|
29
|
+
data: any[]
|
|
30
|
+
requestId: string
|
|
31
|
+
total?: number
|
|
32
|
+
limit?: number
|
|
33
|
+
offset?: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface UpdateResult {
|
|
37
|
+
requestId: string
|
|
38
|
+
updated: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface DeleteResult {
|
|
42
|
+
requestId: string
|
|
43
|
+
deleted: number | string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface TcbError {
|
|
47
|
+
requestId: string
|
|
48
|
+
code: string
|
|
49
|
+
message: string
|
|
50
|
+
stack?: string
|
|
51
|
+
}
|
|
2
52
|
|
|
3
53
|
/**
|
|
4
|
-
*
|
|
54
|
+
* 事务查询模块
|
|
5
55
|
*
|
|
56
|
+
* 支持 where 条件查询在事务中使用
|
|
6
57
|
*/
|
|
7
58
|
export class Query {
|
|
8
59
|
/**
|
|
@@ -14,8 +65,310 @@ export class Query {
|
|
|
14
65
|
|
|
15
66
|
protected _transaction: Transaction
|
|
16
67
|
|
|
17
|
-
|
|
68
|
+
/**
|
|
69
|
+
* 过滤条件
|
|
70
|
+
*
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
private _fieldFilters: Object
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 排序条件
|
|
77
|
+
*
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
private _fieldOrders: QueryOrder[]
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 查询条件
|
|
84
|
+
*
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
private _queryOptions: QueryOption
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 请求实例
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
private _request: TransactionAPI
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 事务ID
|
|
98
|
+
*
|
|
99
|
+
* @internal
|
|
100
|
+
*/
|
|
101
|
+
private _transactionId: string
|
|
102
|
+
|
|
103
|
+
constructor(
|
|
104
|
+
transaction: Transaction,
|
|
105
|
+
coll: string,
|
|
106
|
+
fieldFilters?: Object,
|
|
107
|
+
fieldOrders?: QueryOrder[],
|
|
108
|
+
queryOptions?: QueryOption
|
|
109
|
+
) {
|
|
18
110
|
this._coll = coll
|
|
19
111
|
this._transaction = transaction
|
|
112
|
+
this._fieldFilters = fieldFilters
|
|
113
|
+
this._fieldOrders = fieldOrders || []
|
|
114
|
+
this._queryOptions = queryOptions || {}
|
|
115
|
+
this._request = this._transaction.getRequestMethod()
|
|
116
|
+
this._transactionId = this._transaction.getTransactionId()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 查询条件
|
|
121
|
+
*
|
|
122
|
+
* @param query - 查询条件对象
|
|
123
|
+
*/
|
|
124
|
+
public where(query: object): Query {
|
|
125
|
+
if (Object.prototype.toString.call(query).slice(8, -1) !== 'Object') {
|
|
126
|
+
throw Error(ErrorCode.QueryParamTypeError)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const keys = Object.keys(query)
|
|
130
|
+
const checkFlag = keys.some(item => {
|
|
131
|
+
return query[item] !== undefined
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
if (keys.length && !checkFlag) {
|
|
135
|
+
throw Error(ErrorCode.QueryParamValueError)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return new Query(
|
|
139
|
+
this._transaction,
|
|
140
|
+
this._coll,
|
|
141
|
+
QuerySerializer.encode(query),
|
|
142
|
+
this._fieldOrders,
|
|
143
|
+
this._queryOptions
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 设置排序方式
|
|
149
|
+
*
|
|
150
|
+
* @param fieldPath - 字段路径
|
|
151
|
+
* @param directionStr - 排序方式
|
|
152
|
+
*/
|
|
153
|
+
public orderBy(fieldPath: string, directionStr: OrderByDirection): Query {
|
|
154
|
+
Validate.isFieldPath(fieldPath)
|
|
155
|
+
Validate.isFieldOrder(directionStr)
|
|
156
|
+
|
|
157
|
+
const newOrder: QueryOrder = {
|
|
158
|
+
field: fieldPath,
|
|
159
|
+
direction: directionStr
|
|
160
|
+
}
|
|
161
|
+
const combinedOrders = this._fieldOrders.concat(newOrder)
|
|
162
|
+
|
|
163
|
+
return new Query(
|
|
164
|
+
this._transaction,
|
|
165
|
+
this._coll,
|
|
166
|
+
this._fieldFilters,
|
|
167
|
+
combinedOrders,
|
|
168
|
+
this._queryOptions
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 设置查询条数
|
|
174
|
+
*
|
|
175
|
+
* @param limit - 限制条数
|
|
176
|
+
*/
|
|
177
|
+
public limit(limit: number): Query {
|
|
178
|
+
Validate.isInteger('limit', limit)
|
|
179
|
+
|
|
180
|
+
let option = { ...this._queryOptions }
|
|
181
|
+
option.limit = limit
|
|
182
|
+
|
|
183
|
+
return new Query(
|
|
184
|
+
this._transaction,
|
|
185
|
+
this._coll,
|
|
186
|
+
this._fieldFilters,
|
|
187
|
+
this._fieldOrders,
|
|
188
|
+
option
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 设置偏移量
|
|
194
|
+
*
|
|
195
|
+
* @param offset - 偏移量
|
|
196
|
+
*/
|
|
197
|
+
public skip(offset: number): Query {
|
|
198
|
+
Validate.isInteger('offset', offset)
|
|
199
|
+
|
|
200
|
+
let option = { ...this._queryOptions }
|
|
201
|
+
option.offset = offset
|
|
202
|
+
|
|
203
|
+
return new Query(
|
|
204
|
+
this._transaction,
|
|
205
|
+
this._coll,
|
|
206
|
+
this._fieldFilters,
|
|
207
|
+
this._fieldOrders,
|
|
208
|
+
option
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 指定要返回的字段
|
|
214
|
+
*
|
|
215
|
+
* @param projection
|
|
216
|
+
*/
|
|
217
|
+
public field(projection: any): Query {
|
|
218
|
+
for (let k in projection) {
|
|
219
|
+
if (projection[k]) {
|
|
220
|
+
if (typeof projection[k] !== 'object') {
|
|
221
|
+
projection[k] = 1
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
projection[k] = 0
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let option = { ...this._queryOptions }
|
|
229
|
+
option.projection = projection
|
|
230
|
+
|
|
231
|
+
return new Query(
|
|
232
|
+
this._transaction,
|
|
233
|
+
this._coll,
|
|
234
|
+
this._fieldFilters,
|
|
235
|
+
this._fieldOrders,
|
|
236
|
+
option
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* 发起请求获取文档列表(事务内)
|
|
242
|
+
*/
|
|
243
|
+
public async get(): Promise<GetResult> {
|
|
244
|
+
let newOrder = []
|
|
245
|
+
if (this._fieldOrders) {
|
|
246
|
+
this._fieldOrders.forEach(order => {
|
|
247
|
+
newOrder.push(order)
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
let param: any = {
|
|
252
|
+
collectionName: this._coll,
|
|
253
|
+
transactionId: this._transactionId
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (this._fieldFilters) {
|
|
257
|
+
param.query = this._fieldFilters
|
|
258
|
+
}
|
|
259
|
+
if (newOrder.length > 0) {
|
|
260
|
+
param.order = newOrder
|
|
261
|
+
}
|
|
262
|
+
if (this._queryOptions.offset) {
|
|
263
|
+
param.offset = this._queryOptions.offset
|
|
264
|
+
}
|
|
265
|
+
if (this._queryOptions.limit) {
|
|
266
|
+
param.limit = this._queryOptions.limit < 1000 ? this._queryOptions.limit : 1000
|
|
267
|
+
} else {
|
|
268
|
+
param.limit = 100
|
|
269
|
+
}
|
|
270
|
+
if (this._queryOptions.projection) {
|
|
271
|
+
param.projection = this._queryOptions.projection
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const res = await this._request.send(GET_DOC, param)
|
|
275
|
+
if (res.code) throw res
|
|
276
|
+
|
|
277
|
+
const data = res.data !== 'null' ? EJSON.parse(res.data) : null
|
|
278
|
+
const documents = data ? (Array.isArray(data) ? Util.formatResDocumentData(data) : [Util.formatField(data)]) : []
|
|
279
|
+
|
|
280
|
+
const result: GetResult = {
|
|
281
|
+
data: documents,
|
|
282
|
+
requestId: res.requestId
|
|
283
|
+
}
|
|
284
|
+
if (res.total !== undefined) result.total = res.total
|
|
285
|
+
if (res.limit !== undefined) result.limit = res.limit
|
|
286
|
+
if (res.offset !== undefined) result.offset = res.offset
|
|
287
|
+
|
|
288
|
+
return result
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 获取总数(事务内)
|
|
293
|
+
*/
|
|
294
|
+
public async count(): Promise<{ requestId: string; total: number }> {
|
|
295
|
+
let param: any = {
|
|
296
|
+
collectionName: this._coll,
|
|
297
|
+
transactionId: this._transactionId
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (this._fieldFilters) {
|
|
301
|
+
param.query = this._fieldFilters
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const res = await this._request.send(GET_DOC, param)
|
|
305
|
+
if (res.code) throw res
|
|
306
|
+
|
|
307
|
+
const data = res.data !== 'null' ? EJSON.parse(res.data) : null
|
|
308
|
+
const total = Array.isArray(data) ? data.length : (data ? 1 : 0)
|
|
309
|
+
|
|
310
|
+
return {
|
|
311
|
+
requestId: res.requestId,
|
|
312
|
+
total: res.total !== undefined ? res.total : total
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* 发起请求批量更新文档(事务内)
|
|
318
|
+
*
|
|
319
|
+
* @param data - 更新数据
|
|
320
|
+
*/
|
|
321
|
+
public async update(data: Object): Promise<UpdateResult> {
|
|
322
|
+
if (!data || typeof data !== 'object') {
|
|
323
|
+
throw new Error('参数必需是非空对象')
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (data.hasOwnProperty('_id')) {
|
|
327
|
+
throw new Error('不能更新_id的值')
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const param = {
|
|
331
|
+
collectionName: this._coll,
|
|
332
|
+
transactionId: this._transactionId,
|
|
333
|
+
query: this._fieldFilters,
|
|
334
|
+
data: EJSON.stringify(
|
|
335
|
+
UpdateSerializer.encode(data),
|
|
336
|
+
{ relaxed: false }
|
|
337
|
+
)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const res = await this._request.send(UPDATE_DOC, param)
|
|
341
|
+
if (res.code) throw res
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
...res,
|
|
345
|
+
updated: EJSON.parse(res.updated)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* 条件删除文档(事务内)
|
|
351
|
+
*/
|
|
352
|
+
public async remove(): Promise<DeleteResult> {
|
|
353
|
+
if (Object.keys(this._queryOptions).length > 0) {
|
|
354
|
+
console.warn('`offset`, `limit` and `projection` are not supported in remove() operation')
|
|
355
|
+
}
|
|
356
|
+
if (this._fieldOrders.length > 0) {
|
|
357
|
+
console.warn('`orderBy` is not supported in remove() operation')
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const param = {
|
|
361
|
+
collectionName: this._coll,
|
|
362
|
+
transactionId: this._transactionId,
|
|
363
|
+
query: this._fieldFilters
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const res: DeleteResult | TcbError = await this._request.send(DELETE_DOC, param)
|
|
367
|
+
if ((res as TcbError).code) throw res
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
...res,
|
|
371
|
+
deleted: EJSON.parse((res as DeleteResult).deleted as any) as any
|
|
372
|
+
}
|
|
20
373
|
}
|
|
21
374
|
}
|