@travetto/model-mongo 8.0.4 → 8.0.6
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 +1 -1
- package/package.json +4 -4
- package/src/service.ts +34 -32
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Supported features:
|
|
|
21
21
|
* [CRUD](https://github.com/travetto/travetto/tree/main/module/model/src/types/crud.ts#L10)
|
|
22
22
|
* [Expiry](https://github.com/travetto/travetto/tree/main/module/model/src/types/expiry.ts#L10)
|
|
23
23
|
* [Indexed](https://github.com/travetto/travetto/tree/main/module/model-indexed/src/types/service.ts#L21)
|
|
24
|
-
* [Aggregate](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/aggregate.ts#
|
|
24
|
+
* [Aggregate](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/aggregate.ts#L56)
|
|
25
25
|
* [Query Crud](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/crud.ts#L11)
|
|
26
26
|
* [Facet](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/facet.ts#L14)
|
|
27
27
|
* [Suggest](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/suggest.ts#L12)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/model-mongo",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.6",
|
|
4
4
|
"description": "Mongo backing for the travetto model module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@travetto/config": "^8.0.3",
|
|
33
|
-
"@travetto/model": "^8.0.
|
|
34
|
-
"@travetto/model-indexed": "^8.0.
|
|
35
|
-
"@travetto/model-query": "^8.0.
|
|
33
|
+
"@travetto/model": "^8.0.4",
|
|
34
|
+
"@travetto/model-indexed": "^8.0.4",
|
|
35
|
+
"@travetto/model-query": "^8.0.6",
|
|
36
36
|
"mongodb": "^7.6.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
package/src/service.ts
CHANGED
|
@@ -63,10 +63,10 @@ import {
|
|
|
63
63
|
ModelQuerySuggestUtil,
|
|
64
64
|
type ModelQuerySupport,
|
|
65
65
|
ModelQueryUtil,
|
|
66
|
+
type NumberFieldAggregateResult,
|
|
66
67
|
type PageableModelQuery,
|
|
67
68
|
QueryVerifier,
|
|
68
69
|
type ValidComparableFields,
|
|
69
|
-
type ValidNumericFields,
|
|
70
70
|
type ValidStringFields,
|
|
71
71
|
type WhereClause
|
|
72
72
|
} from '@travetto/model-query';
|
|
@@ -80,7 +80,6 @@ import {
|
|
|
80
80
|
type Class,
|
|
81
81
|
castTo,
|
|
82
82
|
JSONUtil,
|
|
83
|
-
RuntimeError,
|
|
84
83
|
ShutdownManager,
|
|
85
84
|
TypedObject
|
|
86
85
|
} from '@travetto/runtime';
|
|
@@ -105,6 +104,13 @@ const handleDuplicateKeyError = (cls: Class, id: string, error: unknown): unknow
|
|
|
105
104
|
return error;
|
|
106
105
|
};
|
|
107
106
|
|
|
107
|
+
function isNotFoundError(error: unknown): error is MongoServerError {
|
|
108
|
+
return (
|
|
109
|
+
(error instanceof MongoServerError && (error.code === 26 || error.codeName === 'NamespaceNotFound')) ||
|
|
110
|
+
(error instanceof Error && /ns not found/i.test(error.message))
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
108
114
|
export const ModelBlobNamespace = '__blobs';
|
|
109
115
|
|
|
110
116
|
/**
|
|
@@ -257,13 +263,15 @@ export class MongoModelService
|
|
|
257
263
|
async createStorage(): Promise<void> {}
|
|
258
264
|
|
|
259
265
|
async deleteStorage(): Promise<void> {
|
|
260
|
-
await this.#db.dropDatabase();
|
|
266
|
+
await ModelStorageUtil.runAndIgnoreNotFound(() => this.#db.dropDatabase(), isNotFoundError);
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
async upsertModel(cls: Class): Promise<void> {
|
|
264
270
|
const col = await this.getStore(cls);
|
|
265
271
|
const indices = [...ModelRegistryIndex.getIndices(cls).map(idx => MongoUtil.getIndex(cls, idx)), ...MongoUtil.getExtraIndices(cls)];
|
|
266
|
-
const existingIndices = (await
|
|
272
|
+
const existingIndices = ((await ModelStorageUtil.runAndIgnoreNotFound(() => col.indexes(), isNotFoundError)) ?? []).filter(
|
|
273
|
+
idx => idx.name !== '_id_'
|
|
274
|
+
);
|
|
267
275
|
|
|
268
276
|
const pendingMap = Object.fromEntries(indices.map(pair => [pair[1].name!, pair]));
|
|
269
277
|
const existingMap = Object.fromEntries(existingIndices.map(idx => [idx.name!, idx.key]));
|
|
@@ -290,13 +298,17 @@ export class MongoModelService
|
|
|
290
298
|
}
|
|
291
299
|
}
|
|
292
300
|
|
|
301
|
+
async deleteModel<T extends ModelType>(cls: Class<T>): Promise<void> {
|
|
302
|
+
await ModelStorageUtil.runAndIgnoreNotFound(() => this.#db.collection(ModelRegistryIndex.getStoreName(cls)).drop(), isNotFoundError);
|
|
303
|
+
}
|
|
304
|
+
|
|
293
305
|
async truncateModel<T extends ModelType>(cls: Class<T>): Promise<void> {
|
|
294
306
|
const col = await this.getStore(cls);
|
|
295
307
|
await col.deleteMany({});
|
|
296
308
|
}
|
|
297
309
|
|
|
298
310
|
async truncateBlob(): Promise<void> {
|
|
299
|
-
await this.#bucket.drop()
|
|
311
|
+
await this.#bucket.drop();
|
|
300
312
|
}
|
|
301
313
|
|
|
302
314
|
/**
|
|
@@ -738,7 +750,7 @@ export class MongoModelService
|
|
|
738
750
|
}
|
|
739
751
|
|
|
740
752
|
// Aggregate
|
|
741
|
-
async aggregateFieldByQuery<T extends ModelType, F extends ValidComparableFields<T>>(
|
|
753
|
+
async aggregateFieldByQuery<T extends ModelType, const F extends ValidComparableFields<T>>(
|
|
742
754
|
cls: Class<T>,
|
|
743
755
|
field: F,
|
|
744
756
|
query?: ModelQuery<T>
|
|
@@ -747,38 +759,28 @@ export class MongoModelService
|
|
|
747
759
|
|
|
748
760
|
const collection = await this.getStore(cls);
|
|
749
761
|
|
|
750
|
-
const where = ModelQueryUtil.getWhereClause(cls,
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
if (where) {
|
|
754
|
-
queryObject = { $and: [queryObject, MongoUtil.extractWhereFilter(cls, where)] };
|
|
755
|
-
}
|
|
762
|
+
const where = ModelQueryUtil.getWhereClause(cls, {
|
|
763
|
+
$and: [query?.where ?? {}, { [field]: { $exists: true } }]
|
|
764
|
+
});
|
|
756
765
|
|
|
757
|
-
const isDate = SchemaRegistryIndex.getNestedFieldConfig(cls, field)
|
|
766
|
+
const isDate = SchemaRegistryIndex.getNestedFieldConfig(cls, field)?.type === Date;
|
|
758
767
|
|
|
759
768
|
const groupFields: Record<string, unknown> = {
|
|
760
769
|
_id: null,
|
|
761
770
|
count: { $sum: 1 },
|
|
762
|
-
min: { $min: `$${
|
|
763
|
-
max: { $max: `$${
|
|
771
|
+
min: { $min: `$${field}` },
|
|
772
|
+
max: { $max: `$${field}` },
|
|
773
|
+
...(isDate
|
|
774
|
+
? {}
|
|
775
|
+
: {
|
|
776
|
+
avg: { $avg: `$${field}` },
|
|
777
|
+
sum: { $sum: `$${field}` }
|
|
778
|
+
})
|
|
764
779
|
};
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
const aggregations: object[] = [{ $match: queryObject }, { $group: groupFields }];
|
|
771
|
-
|
|
772
|
-
const result = await collection
|
|
773
|
-
.aggregate<{
|
|
774
|
-
_id: null;
|
|
775
|
-
count?: number;
|
|
776
|
-
min?: unknown;
|
|
777
|
-
max?: unknown;
|
|
778
|
-
avg?: unknown;
|
|
779
|
-
sum?: unknown;
|
|
780
|
-
}>(aggregations)
|
|
781
|
-
.toArray();
|
|
780
|
+
|
|
781
|
+
const aggregations: object[] = [{ $match: MongoUtil.extractWhereFilter(cls, where) }, { $group: groupFields }];
|
|
782
|
+
|
|
783
|
+
const result = await collection.aggregate<NumberFieldAggregateResult>(aggregations).toArray();
|
|
782
784
|
|
|
783
785
|
const row = result.length ? result[0] : { count: 0 };
|
|
784
786
|
return ModelQueryAggregateUtil.resolveAggregate(cls, field, row);
|