@opra/mongodb 0.32.3 → 0.32.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/adapter-utils/prepare-filter.js +7 -3
- package/cjs/mongo-array-service.js +215 -57
- package/cjs/mongo-collection-service.js +133 -29
- package/cjs/mongo-service.js +182 -106
- package/cjs/mongo-singleton-service.js +114 -17
- package/esm/adapter-utils/prepare-filter.js +7 -3
- package/esm/mongo-array-service.js +215 -57
- package/esm/mongo-collection-service.js +133 -29
- package/esm/mongo-service.js +182 -106
- package/esm/mongo-singleton-service.js +114 -17
- package/package.json +4 -6
- package/types/adapter-utils/prepare-filter.d.ts +8 -5
- package/types/mongo-array-service.d.ts +106 -33
- package/types/mongo-collection-service.d.ts +78 -24
- package/types/mongo-service.d.ts +157 -62
- package/types/mongo-singleton-service.d.ts +82 -16
|
@@ -12,9 +12,13 @@ const opMap = {
|
|
|
12
12
|
'!in': '$nin',
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @param filters
|
|
15
|
+
* Prepare the MongoDB filter based on the provided filters and options.
|
|
16
|
+
*
|
|
17
|
+
* @param {FilterInput|FilterInput[]} filters - The filter(s) to be applied.
|
|
18
|
+
* @param {Object} [options] - Additional options.
|
|
19
|
+
* @param {string} [options.fieldPrefix] - The prefix to be added to field names.
|
|
20
|
+
*
|
|
21
|
+
* @returns {mongodb.Filter<any>} - The prepared MongoDB filter.
|
|
18
22
|
*/
|
|
19
23
|
function prepareFilter(filters, options) {
|
|
20
24
|
const filtersArray = Array.isArray(filters) ? filters : [filters];
|
|
@@ -12,25 +12,23 @@ const mongo_service_js_1 = require("./mongo-service.js");
|
|
|
12
12
|
* @template T The type of the array item.
|
|
13
13
|
*/
|
|
14
14
|
class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
15
|
+
/**
|
|
16
|
+
* Constructs a new instance
|
|
17
|
+
*
|
|
18
|
+
* @param {Type | string} dataType - The data type of the array elements.
|
|
19
|
+
* @param {string} fieldName - The name of the field in the document representing the array.
|
|
20
|
+
* @param {MongoArrayService.Options} [options] - The options for the array service.
|
|
21
|
+
* @constructor
|
|
22
|
+
*/
|
|
15
23
|
constructor(dataType, fieldName, options) {
|
|
16
24
|
super(dataType, options);
|
|
17
25
|
this.fieldName = fieldName;
|
|
18
26
|
this.defaultLimit = options?.defaultLimit || 10;
|
|
19
27
|
this.collectionKey = options?.collectionKey || '_id';
|
|
20
28
|
this.arrayKey = options?.arrayKey || '_id';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
* @returns {ComplexType} The complex data type of the field.
|
|
26
|
-
* @throws {NotAcceptableError} If the data type is not a ComplexType.
|
|
27
|
-
*/
|
|
28
|
-
getDataType() {
|
|
29
|
-
const t = super.getDataType()
|
|
30
|
-
.getField(this.fieldName).type;
|
|
31
|
-
if (!(t instanceof common_1.ComplexType))
|
|
32
|
-
throw new common_1.NotAcceptableError(`Data type "${t.name}" is not a ComplexType`);
|
|
33
|
-
return t;
|
|
29
|
+
this.$documentFilter = options?.documentFilter;
|
|
30
|
+
this.$arrayFilter = options?.arrayFilter;
|
|
31
|
+
this.$interceptor = this.$interceptor || options?.interceptor;
|
|
34
32
|
}
|
|
35
33
|
/**
|
|
36
34
|
* Asserts whether a resource with the specified parentId and id exists.
|
|
@@ -38,12 +36,13 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
38
36
|
*
|
|
39
37
|
* @param {AnyId} documentId - The ID of the parent document.
|
|
40
38
|
* @param {AnyId} id - The ID of the resource.
|
|
39
|
+
* @param {MongoArrayService.ExistsOptions} [options] - Optional parameters for checking resource existence.
|
|
41
40
|
* @return {Promise<void>} - A promise that resolves with no value upon success.
|
|
42
41
|
* @throws {ResourceNotFoundError} - If the resource does not exist.
|
|
43
42
|
*/
|
|
44
|
-
async assert(documentId, id) {
|
|
45
|
-
if (!(await this.exists(documentId, id)))
|
|
46
|
-
throw new common_1.ResourceNotFoundError(
|
|
43
|
+
async assert(documentId, id, options) {
|
|
44
|
+
if (!(await this.exists(documentId, id, options)))
|
|
45
|
+
throw new common_1.ResourceNotFoundError(this.getResourceName() + '.' + this.arrayKey, documentId + '/' + id);
|
|
47
46
|
}
|
|
48
47
|
/**
|
|
49
48
|
* Adds a single item into the array field.
|
|
@@ -51,13 +50,22 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
51
50
|
* @param {AnyId} documentId - The ID of the parent document.
|
|
52
51
|
* @param {T} input - The item to be added to the array field.
|
|
53
52
|
* @param {MongoArrayService.CreateOptions} [options] - Optional options for the create operation.
|
|
54
|
-
* @return {Promise<
|
|
53
|
+
* @return {Promise<PartialDTO<T>>} - A promise that resolves with the partial output of the created item.
|
|
55
54
|
* @throws {ResourceNotFoundError} - If the parent document is not found.
|
|
56
55
|
*/
|
|
57
56
|
async create(documentId, input, options) {
|
|
57
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
58
|
+
return this.$interceptor(() => this.create(documentId, input, { ...options, __interceptor__: true }), {
|
|
59
|
+
crud: 'create',
|
|
60
|
+
method: 'create',
|
|
61
|
+
documentId,
|
|
62
|
+
itemId: input._id,
|
|
63
|
+
input,
|
|
64
|
+
options
|
|
65
|
+
}, this);
|
|
58
66
|
const encode = this.getEncoder('create');
|
|
59
67
|
const doc = encode(input);
|
|
60
|
-
doc
|
|
68
|
+
doc._id = doc._id || this._generateId();
|
|
61
69
|
const docFilter = mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, [this.collectionKey]);
|
|
62
70
|
const r = await this.__updateOne(docFilter, {
|
|
63
71
|
$push: { [this.fieldName]: doc }
|
|
@@ -73,7 +81,7 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
73
81
|
throw e;
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
|
-
throw new common_1.ResourceNotFoundError(this.
|
|
84
|
+
throw new common_1.ResourceNotFoundError(this.getResourceName(), documentId);
|
|
77
85
|
}
|
|
78
86
|
/**
|
|
79
87
|
* Counts the number of documents in the collection that match the specified parentId and options.
|
|
@@ -84,14 +92,25 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
84
92
|
* @returns {Promise<number>} - A promise that resolves to the count of documents.
|
|
85
93
|
*/
|
|
86
94
|
async count(documentId, options) {
|
|
87
|
-
|
|
95
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
96
|
+
return this.$interceptor(() => this.count(documentId, { ...options, __interceptor__: true }), {
|
|
97
|
+
crud: 'read',
|
|
98
|
+
method: 'count',
|
|
99
|
+
documentId,
|
|
100
|
+
options
|
|
101
|
+
}, this);
|
|
102
|
+
const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
103
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, [this.collectionKey]),
|
|
104
|
+
await this._getDocumentFilter()
|
|
105
|
+
]);
|
|
88
106
|
const stages = [
|
|
89
107
|
{ $match: matchFilter },
|
|
90
108
|
{ $unwind: { path: "$" + this.fieldName } },
|
|
91
109
|
{ $replaceRoot: { newRoot: "$" + this.fieldName } }
|
|
92
110
|
];
|
|
93
|
-
|
|
94
|
-
|
|
111
|
+
const contextArrayFilter = await this._getArrayFilter();
|
|
112
|
+
if (options?.filter || contextArrayFilter) {
|
|
113
|
+
const optionsFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter, contextArrayFilter]);
|
|
95
114
|
stages.push({ $match: optionsFilter });
|
|
96
115
|
}
|
|
97
116
|
stages.push({ $count: '*' });
|
|
@@ -113,11 +132,23 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
113
132
|
* @return {Promise<number>} - A Promise that resolves to the number of elements deleted (1 if successful, 0 if not).
|
|
114
133
|
*/
|
|
115
134
|
async delete(documentId, id, options) {
|
|
116
|
-
|
|
135
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
136
|
+
return this.$interceptor(() => this.delete(documentId, id, { ...options, __interceptor__: true }), {
|
|
137
|
+
crud: 'delete',
|
|
138
|
+
method: 'delete',
|
|
139
|
+
documentId,
|
|
140
|
+
itemId: id,
|
|
141
|
+
options
|
|
142
|
+
}, this);
|
|
143
|
+
const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
144
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, [this.collectionKey]),
|
|
145
|
+
await this._getDocumentFilter()
|
|
146
|
+
]);
|
|
117
147
|
const pullFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
118
148
|
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(id, [this.arrayKey]),
|
|
119
|
-
options?.filter
|
|
120
|
-
|
|
149
|
+
options?.filter,
|
|
150
|
+
await this._getArrayFilter()
|
|
151
|
+
]) || {};
|
|
121
152
|
const r = await this.__updateOne(matchFilter, {
|
|
122
153
|
$pull: { [this.fieldName]: pullFilter }
|
|
123
154
|
}, options);
|
|
@@ -131,11 +162,24 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
131
162
|
* @returns {Promise<number>} - A Promise that resolves to the number of items deleted.
|
|
132
163
|
*/
|
|
133
164
|
async deleteMany(documentId, options) {
|
|
134
|
-
|
|
165
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
166
|
+
return this.$interceptor(() => this.deleteMany(documentId, { ...options, __interceptor__: true }), {
|
|
167
|
+
crud: 'delete',
|
|
168
|
+
method: 'deleteMany',
|
|
169
|
+
documentId,
|
|
170
|
+
options
|
|
171
|
+
}, this);
|
|
172
|
+
const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
173
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, [this.collectionKey]),
|
|
174
|
+
await this._getDocumentFilter()
|
|
175
|
+
]);
|
|
135
176
|
// Count matching items, we will use this as result
|
|
136
177
|
const matchCount = await this.count(documentId, options);
|
|
137
|
-
const pullFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter(
|
|
138
|
-
|
|
178
|
+
const pullFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
179
|
+
options?.filter,
|
|
180
|
+
await this._getArrayFilter()
|
|
181
|
+
]) || {};
|
|
182
|
+
const r = await this.__updateOne(matchFilter, {
|
|
139
183
|
$pull: { [this.fieldName]: pullFilter }
|
|
140
184
|
}, options);
|
|
141
185
|
if (r.modifiedCount)
|
|
@@ -147,10 +191,19 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
147
191
|
*
|
|
148
192
|
* @param {AnyId} documentId - The ID of the parent document.
|
|
149
193
|
* @param {AnyId} id - The id of the record.
|
|
194
|
+
* @param {MongoArrayService.ExistsOptions} [options] - The options for the exists method.
|
|
150
195
|
* @returns {Promise<boolean>} - A promise that resolves to a boolean indicating if the record exists or not.
|
|
151
196
|
*/
|
|
152
|
-
async exists(documentId, id) {
|
|
153
|
-
|
|
197
|
+
async exists(documentId, id, options) {
|
|
198
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
199
|
+
return this.$interceptor(() => this.exists(documentId, id, { ...options, __interceptor__: true }), {
|
|
200
|
+
crud: 'read',
|
|
201
|
+
method: 'exists',
|
|
202
|
+
documentId,
|
|
203
|
+
itemId: id,
|
|
204
|
+
options
|
|
205
|
+
}, this);
|
|
206
|
+
return !!(await this.findById(documentId, id, { ...options, pick: ['_id'] }));
|
|
154
207
|
}
|
|
155
208
|
/**
|
|
156
209
|
* Finds an element in array field by its parent ID and ID.
|
|
@@ -158,12 +211,21 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
158
211
|
* @param {AnyId} documentId - The ID of the document.
|
|
159
212
|
* @param {AnyId} id - The ID of the document.
|
|
160
213
|
* @param {MongoArrayService.FindOneOptions} [options] - The optional options for the operation.
|
|
161
|
-
* @returns {Promise<
|
|
214
|
+
* @returns {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the found document or undefined if not found.
|
|
162
215
|
*/
|
|
163
216
|
async findById(documentId, id, options) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
217
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
218
|
+
return this.$interceptor(() => this.findOne(documentId, { ...options, __interceptor__: true }), {
|
|
219
|
+
crud: 'read',
|
|
220
|
+
method: 'findById',
|
|
221
|
+
documentId,
|
|
222
|
+
itemId: id,
|
|
223
|
+
options
|
|
224
|
+
}, this);
|
|
225
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
226
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(id, [this.arrayKey]),
|
|
227
|
+
options?.filter
|
|
228
|
+
]);
|
|
167
229
|
return await this.findOne(documentId, { ...options, filter });
|
|
168
230
|
}
|
|
169
231
|
/**
|
|
@@ -171,9 +233,16 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
171
233
|
*
|
|
172
234
|
* @param {AnyId} documentId - The ID of the document.
|
|
173
235
|
* @param {MongoArrayService.FindOneOptions} [options] - Optional options to customize the query.
|
|
174
|
-
* @returns {Promise<
|
|
236
|
+
* @returns {Promise<PartialDTO<T> | undefined>} A promise that resolves to the first matching document, or `undefined` if no match is found.
|
|
175
237
|
*/
|
|
176
238
|
async findOne(documentId, options) {
|
|
239
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
240
|
+
return this.$interceptor(() => this.findOne(documentId, { ...options, __interceptor__: true }), {
|
|
241
|
+
crud: 'read',
|
|
242
|
+
method: 'findOne',
|
|
243
|
+
documentId,
|
|
244
|
+
options
|
|
245
|
+
}, this);
|
|
177
246
|
const rows = await this.findMany(documentId, {
|
|
178
247
|
...options,
|
|
179
248
|
limit: 1
|
|
@@ -185,10 +254,20 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
185
254
|
*
|
|
186
255
|
* @param {AnyId} documentId - The ID of the parent document.
|
|
187
256
|
* @param {MongoArrayService.FindManyOptions<T>} [options] - The options for finding the documents.
|
|
188
|
-
* @returns {Promise<
|
|
257
|
+
* @returns {Promise<PartialDTO<T>[]>} - The found documents.
|
|
189
258
|
*/
|
|
190
259
|
async findMany(documentId, options) {
|
|
191
|
-
|
|
260
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
261
|
+
return this.$interceptor(() => this.findMany(documentId, { ...options, __interceptor__: true }), {
|
|
262
|
+
crud: 'read',
|
|
263
|
+
method: 'findMany',
|
|
264
|
+
documentId,
|
|
265
|
+
options
|
|
266
|
+
}, this);
|
|
267
|
+
const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
268
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, [this.collectionKey]),
|
|
269
|
+
await this._getDocumentFilter()
|
|
270
|
+
]);
|
|
192
271
|
const mongoOptions = {
|
|
193
272
|
...(0, lodash_omit_1.default)(options, ['pick', 'include', 'omit', 'sort', 'skip', 'limit', 'filter', 'count'])
|
|
194
273
|
};
|
|
@@ -208,8 +287,12 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
208
287
|
}
|
|
209
288
|
});
|
|
210
289
|
}
|
|
211
|
-
|
|
212
|
-
|
|
290
|
+
const contextArrayFilter = await this._getArrayFilter();
|
|
291
|
+
if (options?.filter || contextArrayFilter) {
|
|
292
|
+
const optionsFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
293
|
+
options?.filter,
|
|
294
|
+
contextArrayFilter
|
|
295
|
+
]);
|
|
213
296
|
dataStages.push({ $match: optionsFilter });
|
|
214
297
|
}
|
|
215
298
|
if (options?.skip)
|
|
@@ -248,13 +331,13 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
248
331
|
* @param {AnyId} documentId - The ID of the document.
|
|
249
332
|
* @param {AnyId} id - The ID of the item.
|
|
250
333
|
* @param {MongoArrayService.FindOneOptions<T>} [options] - The options for finding the item.
|
|
251
|
-
* @returns {Promise<
|
|
334
|
+
* @returns {Promise<PartialDTO<T>>} - The item found.
|
|
252
335
|
* @throws {ResourceNotFoundError} - If the item is not found.
|
|
253
336
|
*/
|
|
254
337
|
async get(documentId, id, options) {
|
|
255
338
|
const out = await this.findById(documentId, id, options);
|
|
256
339
|
if (!out)
|
|
257
|
-
throw new common_1.ResourceNotFoundError(
|
|
340
|
+
throw new common_1.ResourceNotFoundError(this.getResourceName() + '.' + this.arrayKey, documentId + '/' + id);
|
|
258
341
|
return out;
|
|
259
342
|
}
|
|
260
343
|
/**
|
|
@@ -262,13 +345,23 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
262
345
|
*
|
|
263
346
|
* @param {AnyId} documentId - The ID of the document to update.
|
|
264
347
|
* @param {AnyId} id - The ID of the item to update within the document.
|
|
265
|
-
* @param {
|
|
348
|
+
* @param {PatchDTO<T>} input - The new data to update the item with.
|
|
266
349
|
* @param {MongoArrayService.UpdateOptions<T>} [options] - Additional update options.
|
|
267
|
-
* @returns {Promise<
|
|
350
|
+
* @returns {Promise<PartialDTO<T> | undefined>} The updated item or undefined if it does not exist.
|
|
268
351
|
* @throws {Error} If an error occurs while updating the item.
|
|
269
352
|
*/
|
|
270
353
|
async update(documentId, id, input, options) {
|
|
271
|
-
|
|
354
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
355
|
+
return this.$interceptor(() => this.update(documentId, id, input, { ...options, __interceptor__: true }), {
|
|
356
|
+
crud: 'update',
|
|
357
|
+
method: 'update',
|
|
358
|
+
documentId,
|
|
359
|
+
itemId: id,
|
|
360
|
+
options
|
|
361
|
+
}, this);
|
|
362
|
+
const r = await this.updateOnly(documentId, id, input, options);
|
|
363
|
+
if (!r)
|
|
364
|
+
return;
|
|
272
365
|
try {
|
|
273
366
|
return await this.findById(documentId, id, options);
|
|
274
367
|
}
|
|
@@ -282,40 +375,59 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
282
375
|
*
|
|
283
376
|
* @param {AnyId} documentId - The ID of the parent document.
|
|
284
377
|
* @param {AnyId} id - The ID of the document to update.
|
|
285
|
-
* @param {
|
|
378
|
+
* @param {PatchDTO<T>} input - The partial input object containing the fields to update.
|
|
286
379
|
* @param {MongoArrayService.UpdateOptions<T>} [options] - Optional update options.
|
|
287
380
|
* @returns {Promise<number>} - A promise that resolves to the number of elements updated.
|
|
288
381
|
*/
|
|
289
|
-
async updateOnly(documentId, id,
|
|
382
|
+
async updateOnly(documentId, id, input, options) {
|
|
383
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
384
|
+
return this.$interceptor(() => this.updateOnly(documentId, id, input, { ...options, __interceptor__: true }), {
|
|
385
|
+
crud: 'update',
|
|
386
|
+
method: 'updateOnly',
|
|
387
|
+
documentId,
|
|
388
|
+
itemId: id,
|
|
389
|
+
input,
|
|
390
|
+
options
|
|
391
|
+
}, this);
|
|
290
392
|
let filter = mongo_adapter_js_1.MongoAdapter.prepareKeyValues(id, [this.arrayKey]);
|
|
291
393
|
if (options?.filter)
|
|
292
394
|
filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([filter, options?.filter]);
|
|
293
|
-
return await this.updateMany(documentId,
|
|
395
|
+
return await this.updateMany(documentId, input, { ...options, filter });
|
|
294
396
|
}
|
|
295
397
|
/**
|
|
296
398
|
* Updates multiple array elements in document
|
|
297
399
|
*
|
|
298
400
|
* @param {AnyId} documentId - The ID of the document to update.
|
|
299
|
-
* @param {
|
|
401
|
+
* @param {PatchDTO<T>} input - The updated data for the document(s).
|
|
300
402
|
* @param {MongoArrayService.UpdateManyOptions<T>} [options] - Additional options for the update operation.
|
|
301
403
|
* @returns {Promise<number>} - A promise that resolves to the number of documents updated.
|
|
302
404
|
*/
|
|
303
405
|
async updateMany(documentId, input, options) {
|
|
406
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
407
|
+
return this.$interceptor(() => this.updateMany(documentId, input, { ...options, __interceptor__: true }), {
|
|
408
|
+
crud: 'update',
|
|
409
|
+
method: 'updateMany',
|
|
410
|
+
documentId,
|
|
411
|
+
input,
|
|
412
|
+
options
|
|
413
|
+
}, this);
|
|
304
414
|
const encode = this.getEncoder('update');
|
|
305
415
|
const doc = encode(input);
|
|
306
416
|
if (!Object.keys(doc).length)
|
|
307
417
|
return 0;
|
|
308
418
|
const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
309
419
|
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, [this.collectionKey]),
|
|
420
|
+
await this._getDocumentFilter(),
|
|
310
421
|
{ [this.fieldName]: { $exists: true } }
|
|
311
422
|
]);
|
|
312
|
-
|
|
313
|
-
|
|
423
|
+
const contextArrayFilter = await this._getArrayFilter();
|
|
424
|
+
if (options?.filter || contextArrayFilter) {
|
|
425
|
+
const elemMatch = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter, contextArrayFilter], { fieldPrefix: 'elem.' });
|
|
314
426
|
options = options || {};
|
|
315
427
|
options.arrayFilters = [elemMatch];
|
|
316
428
|
}
|
|
317
429
|
const update = mongo_adapter_js_1.MongoAdapter.preparePatch(doc, {
|
|
318
|
-
fieldPrefix: this.fieldName + (options?.filter ? '.$[elem].' : '.$[].')
|
|
430
|
+
fieldPrefix: this.fieldName + ((options?.filter || contextArrayFilter) ? '.$[elem].' : '.$[].')
|
|
319
431
|
});
|
|
320
432
|
const r = await this.__updateOne(matchFilter, update, options);
|
|
321
433
|
return r.modifiedCount;
|
|
@@ -324,25 +436,71 @@ class MongoArrayService extends mongo_service_js_1.MongoService {
|
|
|
324
436
|
* Updates multiple elements and returns the count of elements that were updated.
|
|
325
437
|
*
|
|
326
438
|
* @param {AnyId} documentId - The ID of the document to update.
|
|
327
|
-
* @param {
|
|
439
|
+
* @param {PatchDTO<T>} input - The partial document to update with.
|
|
328
440
|
* @param {MongoArrayService.UpdateManyOptions<T>} [options] - The options for updating multiple documents.
|
|
329
441
|
* @return {Promise<number>} A promise that resolves to the number of elements updated.
|
|
330
442
|
*/
|
|
331
|
-
async updateManyReturnCount(documentId,
|
|
332
|
-
|
|
443
|
+
async updateManyReturnCount(documentId, input, options) {
|
|
444
|
+
if (this.$interceptor && !options?.__interceptor__)
|
|
445
|
+
return this.$interceptor(() => this.updateManyReturnCount(documentId, input, { ...options, __interceptor__: true }), {
|
|
446
|
+
crud: 'update',
|
|
447
|
+
method: 'updateManyReturnCount',
|
|
448
|
+
documentId,
|
|
449
|
+
input,
|
|
450
|
+
options
|
|
451
|
+
}, this);
|
|
452
|
+
const r = await this.updateMany(documentId, input, options);
|
|
333
453
|
return r
|
|
334
454
|
// Count matching items that fits filter criteria
|
|
335
455
|
? await this.count(documentId, options)
|
|
336
456
|
: 0;
|
|
337
457
|
}
|
|
338
458
|
/**
|
|
339
|
-
*
|
|
459
|
+
* Retrieves the data type of the array field
|
|
460
|
+
*
|
|
461
|
+
* @returns {ComplexType} The complex data type of the field.
|
|
462
|
+
* @throws {NotAcceptableError} If the data type is not a ComplexType.
|
|
463
|
+
*/
|
|
464
|
+
getDataType() {
|
|
465
|
+
const t = super.getDataType()
|
|
466
|
+
.getField(this.fieldName).type;
|
|
467
|
+
if (!(t instanceof common_1.ComplexType))
|
|
468
|
+
throw new common_1.NotAcceptableError(`Data type "${t.name}" is not a ComplexType`);
|
|
469
|
+
return t;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Generates an ID.
|
|
340
473
|
*
|
|
341
474
|
* @protected
|
|
342
|
-
* @returns {AnyId}
|
|
475
|
+
* @returns {AnyId} The generated ID.
|
|
343
476
|
*/
|
|
344
477
|
_generateId() {
|
|
345
|
-
return
|
|
478
|
+
return typeof this.$idGenerator === 'function' ?
|
|
479
|
+
this.$idGenerator(this) : new mongodb_1.ObjectId();
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Retrieves the common filter used for querying documents.
|
|
483
|
+
* This method is mostly used for security issues like securing multi-tenant applications.
|
|
484
|
+
*
|
|
485
|
+
* @protected
|
|
486
|
+
* @returns {FilterInput | Promise<FilterInput> | undefined} The common filter or a Promise
|
|
487
|
+
* that resolves to the common filter, or undefined if not available.
|
|
488
|
+
*/
|
|
489
|
+
_getDocumentFilter() {
|
|
490
|
+
return typeof this.$documentFilter === 'function' ?
|
|
491
|
+
this.$documentFilter(this) : this.$documentFilter;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Retrieves the common filter used for querying array elements.
|
|
495
|
+
* This method is mostly used for security issues like securing multi-tenant applications.
|
|
496
|
+
*
|
|
497
|
+
* @protected
|
|
498
|
+
* @returns {FilterInput | Promise<FilterInput> | undefined} The common filter or a Promise
|
|
499
|
+
* that resolves to the common filter, or undefined if not available.
|
|
500
|
+
*/
|
|
501
|
+
_getArrayFilter() {
|
|
502
|
+
return typeof this.$arrayFilter === 'function' ?
|
|
503
|
+
this.$arrayFilter(this) : this.$arrayFilter;
|
|
346
504
|
}
|
|
347
505
|
}
|
|
348
506
|
exports.MongoArrayService = MongoArrayService;
|