@travetto/model-mongo 8.0.3 → 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.3",
3
+ "version": "8.0.4",
4
4
  "description": "Mongo backing for the travetto model module.",
5
5
  "keywords": [
6
6
  "database",
@@ -32,7 +32,7 @@
32
32
  "@travetto/config": "^8.0.3",
33
33
  "@travetto/model": "^8.0.3",
34
34
  "@travetto/model-indexed": "^8.0.3",
35
- "@travetto/model-query": "^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,11 +640,19 @@ export class MongoModelService
641
640
  return await Promise.all(items.map(item => this.postLoad(cls, item)));
642
641
  }
643
642
 
644
- async queryOne<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>, failOnMany = true): Promise<T> {
643
+ async getByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>, failOnMany = true): Promise<T> {
645
644
  const results = await this.query<T>(cls, { ...query, limit: failOnMany ? 2 : 1 });
646
645
  return ModelQueryUtil.verifyGetSingleCounts<T>(cls, failOnMany, results, query.where);
647
646
  }
648
647
 
648
+ async countByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>): Promise<number> {
649
+ await QueryVerifier.verify(cls, query);
650
+
651
+ const col = await this.getStore(cls);
652
+ const filter = MongoUtil.extractWhereFilter(cls, query.where);
653
+ return col.countDocuments(filter);
654
+ }
655
+
649
656
  // Query Crud
650
657
  async updateByQuery<T extends ModelType>(cls: Class<T>, data: T, query: ModelQuery<T>): Promise<T> {
651
658
  await QueryVerifier.verify(cls, query);
@@ -730,59 +737,51 @@ export class MongoModelService
730
737
  .toSorted((a, b) => b.count - a.count);
731
738
  }
732
739
 
733
- static readonly AGGREGATE_OPERATION_MAPPING: Record<AggregateOperation, '$sum' | '$avg' | '$min' | '$max'> = {
734
- sum: '$sum',
735
- avg: '$avg',
736
- min: '$min',
737
- max: '$max'
738
- };
739
-
740
740
  // Aggregate
741
- async aggregateFieldByQuery<
742
- T extends ModelType,
743
- Op extends AggregateOperation,
744
- F extends (Op extends AggregateNumericOperation ? ValidNumericFields<T> : ValidComparableFields<T>)
745
- >(modelClass: Class<T>, operation: Op, field: F, query?: ModelQuery<T>): Promise<AggregateResultType<T, F>> {
746
- 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);
747
747
 
748
- const collection = await this.getStore(modelClass);
748
+ const collection = await this.getStore(cls);
749
749
 
750
- const where = ModelQueryUtil.getWhereClause(modelClass, query?.where);
750
+ const where = ModelQueryUtil.getWhereClause(cls, query?.where);
751
751
  let queryObject: Record<string, unknown> = { [field]: { $exists: true, $ne: null } };
752
752
 
753
753
  if (where) {
754
- queryObject = { $and: [queryObject, MongoUtil.extractWhereFilter(modelClass, where)] };
754
+ queryObject = { $and: [queryObject, MongoUtil.extractWhereFilter(cls, where)] };
755
755
  }
756
756
 
757
- const aggregateOperator = MongoModelService.AGGREGATE_OPERATION_MAPPING[operation];
758
- if (!aggregateOperator) {
759
- throw new RuntimeError(`Unsupported aggregate operation: ${operation}`);
760
- }
761
-
762
- const aggregations: object[] = [
763
- { $match: queryObject },
764
- {
765
- $group: {
766
- _id: null,
767
- value: {
768
- [aggregateOperator]: `$${String(field)}`
769
- }
770
- }
771
- }
772
- ];
773
-
774
- const result = await collection.aggregate<{ _id: null; value: unknown }>(aggregations).toArray();
775
- const rawValue = result.length ? result[0].value : undefined;
776
-
777
- return ModelQueryAggregateUtil.resolveResult(modelClass, operation, field, rawValue);
778
- }
779
-
780
- async countByQuery<T extends ModelType>(cls: Class<T>, query: ModelQuery<T>): Promise<number> {
781
- await QueryVerifier.verify(cls, query);
757
+ const isDate = SchemaRegistryIndex.getNestedFieldConfig(cls, field)!.type === Date;
782
758
 
783
- const col = await this.getStore(cls);
784
- const filter = MongoUtil.extractWhereFilter(cls, query.where);
785
- return col.countDocuments(filter);
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