@travetto/model-mongo 8.0.2 → 8.0.4

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 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#L30)
24
+ * [Aggregate](https://github.com/travetto/travetto/tree/main/module/model-query/src/types/aggregate.ts#L43)
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.2",
3
+ "version": "8.0.4",
4
4
  "description": "Mongo backing for the travetto model module.",
5
5
  "keywords": [
6
6
  "database",
@@ -29,10 +29,10 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@travetto/config": "^8.0.2",
33
- "@travetto/model": "^8.0.2",
34
- "@travetto/model-indexed": "^8.0.2",
35
- "@travetto/model-query": "^8.0.2",
32
+ "@travetto/config": "^8.0.3",
33
+ "@travetto/model": "^8.0.3",
34
+ "@travetto/model-indexed": "^8.0.3",
35
+ "@travetto/model-query": "^8.0.4",
36
36
  "mongodb": "^7.6.0"
37
37
  },
38
38
  "peerDependencies": {
package/src/service.ts CHANGED
@@ -51,9 +51,7 @@ import {
51
51
  type SortedIndexSelectionType
52
52
  } from '@travetto/model-indexed';
53
53
  import {
54
- type AggregateNumericOperation,
55
- type AggregateOperation,
56
- type AggregateResultType,
54
+ type FieldAggregateResult,
57
55
  type ModelQuery,
58
56
  type ModelQueryAggregateSupport,
59
57
  ModelQueryAggregateUtil,
@@ -86,6 +84,7 @@ import {
86
84
  ShutdownManager,
87
85
  TypedObject
88
86
  } from '@travetto/runtime';
87
+ import { SchemaRegistryIndex } from '@travetto/schema';
89
88
 
90
89
  import type { MongoModelConfig } from './config.ts';
91
90
  import { MongoUtil, type WithId } from './internal/util.ts';
@@ -641,7 +640,12 @@ export class MongoModelService
641
640
  return await Promise.all(items.map(item => this.postLoad(cls, item)));
642
641
  }
643
642
 
644
- async queryCount<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>): Promise<number> {
643
+ async getByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>, failOnMany = true): Promise<T> {
644
+ const results = await this.query<T>(cls, { ...query, limit: failOnMany ? 2 : 1 });
645
+ return ModelQueryUtil.verifyGetSingleCounts<T>(cls, failOnMany, results, query.where);
646
+ }
647
+
648
+ async countByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>): Promise<number> {
645
649
  await QueryVerifier.verify(cls, query);
646
650
 
647
651
  const col = await this.getStore(cls);
@@ -649,11 +653,6 @@ export class MongoModelService
649
653
  return col.countDocuments(filter);
650
654
  }
651
655
 
652
- async queryOne<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>, failOnMany = true): Promise<T> {
653
- const results = await this.query<T>(cls, { ...query, limit: failOnMany ? 2 : 1 });
654
- return ModelQueryUtil.verifyGetSingleCounts<T>(cls, failOnMany, results, query.where);
655
- }
656
-
657
656
  // Query Crud
658
657
  async updateByQuery<T extends ModelType>(cls: Class<T>, data: T, query: ModelQuery<T>): Promise<T> {
659
658
  await QueryVerifier.verify(cls, query);
@@ -738,51 +737,51 @@ export class MongoModelService
738
737
  .toSorted((a, b) => b.count - a.count);
739
738
  }
740
739
 
741
- static readonly AGGREGATE_OPERATION_MAPPING: Record<AggregateOperation, '$sum' | '$avg' | '$min' | '$max'> = {
742
- sum: '$sum',
743
- avg: '$avg',
744
- min: '$min',
745
- max: '$max'
746
- };
747
-
748
740
  // Aggregate
749
- async aggregateFieldByQuery<
750
- T extends ModelType,
751
- Op extends AggregateOperation,
752
- F extends (Op extends AggregateNumericOperation ? ValidNumericFields<T> : ValidComparableFields<T>)
753
- >(modelClass: Class<T>, operation: Op, field: F, query?: ModelQuery<T>): Promise<AggregateResultType<T, F>> {
754
- await QueryVerifier.verify(modelClass, query);
741
+ async aggregateFieldByQuery<T extends ModelType, F extends ValidComparableFields<T>>(
742
+ cls: Class<T>,
743
+ field: F,
744
+ query?: ModelQuery<T>
745
+ ): Promise<FieldAggregateResult<T, F>> {
746
+ await QueryVerifier.verify(cls, query);
755
747
 
756
- const collection = await this.getStore(modelClass);
748
+ const collection = await this.getStore(cls);
757
749
 
758
- const where = ModelQueryUtil.getWhereClause(modelClass, query?.where);
750
+ const where = ModelQueryUtil.getWhereClause(cls, query?.where);
759
751
  let queryObject: Record<string, unknown> = { [field]: { $exists: true, $ne: null } };
760
752
 
761
753
  if (where) {
762
- queryObject = { $and: [queryObject, MongoUtil.extractWhereFilter(modelClass, where)] };
754
+ queryObject = { $and: [queryObject, MongoUtil.extractWhereFilter(cls, where)] };
763
755
  }
764
756
 
765
- const aggregateOperator = MongoModelService.AGGREGATE_OPERATION_MAPPING[operation];
766
- if (!aggregateOperator) {
767
- throw new RuntimeError(`Unsupported aggregate operation: ${operation}`);
768
- }
769
-
770
- const aggregations: object[] = [
771
- { $match: queryObject },
772
- {
773
- $group: {
774
- _id: null,
775
- value: {
776
- [aggregateOperator]: `$${String(field)}`
777
- }
778
- }
779
- }
780
- ];
781
-
782
- const result = await collection.aggregate<{ _id: null; value: unknown }>(aggregations).toArray();
783
- const rawValue = result.length ? result[0].value : undefined;
757
+ const isDate = SchemaRegistryIndex.getNestedFieldConfig(cls, field)!.type === Date;
784
758
 
785
- return ModelQueryAggregateUtil.resolveResult(modelClass, operation, field, rawValue);
759
+ const groupFields: Record<string, unknown> = {
760
+ _id: null,
761
+ count: { $sum: 1 },
762
+ min: { $min: `$${String(field)}` },
763
+ max: { $max: `$${String(field)}` }
764
+ };
765
+ if (!isDate) {
766
+ groupFields.avg = { $avg: `$${String(field)}` };
767
+ groupFields.sum = { $sum: `$${String(field)}` };
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();
782
+
783
+ const row = result.length ? result[0] : { count: 0 };
784
+ return ModelQueryAggregateUtil.resolveAggregate(cls, field, row);
786
785
  }
787
786
 
788
787
  // Suggest