industrial-model 0.3.0 → 0.4.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/README.md CHANGED
@@ -63,6 +63,7 @@ const { items } = await model.query<{ name: string; description: string }>()({
63
63
  | Filters | [AND/OR/NOT](#combine-filters-with-and--or--not), [Nested](#filter-on-related-nodes), [Tags](#filter-assets-by-tags), [Batch IDs](#filter-by-multiple-external-ids) |
64
64
  | Select & sort | [Select all scalars](#select-all-scalar-fields), [Multi-field sort](#sort-by-multiple-fields) |
65
65
  | Pagination | [Manual cursor loop](#paginate-through-all-assets), [Fetch all pages](#fetch-all-pages-automatically) |
66
+ | Aggregation | [Count by group](#count-assets-by-source-id), [Distinct values](#list-distinct-source-ids), [Numeric aggregates](#average-volume-by-type), [Global count](#count-all-matching-assets) |
66
67
  | Advanced | [Custom data model](#use-a-custom-data-model), [Full query](#full-example-assets-equipment-and-filters) |
67
68
 
68
69
  All examples below use the [Cognite Core Data Model](https://docs.cognite.com/cdf/data_modeling/reference_data_models/cognite_core/), space `cdf_cdm`, version `v1`.
@@ -661,6 +662,135 @@ if (cursor) {
661
662
 
662
663
  ---
663
664
 
665
+ ### Count assets by source ID
666
+
667
+ Group assets and count how many share each `sourceId`. Uses the same `filters` syntax as `query`.
668
+
669
+ ```ts
670
+ const { items } = await model.aggregate<CogniteAsset>()({
671
+ viewExternalId: "CogniteAsset",
672
+ groupBy: { sourceId: true },
673
+ aggregate: { count: {} },
674
+ filters: { name: { prefix: "WMT" } },
675
+ });
676
+
677
+ for (const row of items) {
678
+ console.log(row.group?.sourceId, row.aggregate?.value);
679
+ }
680
+ ```
681
+
682
+ ---
683
+
684
+ ### List distinct source IDs
685
+
686
+ Omit `aggregate` to return unique combinations of the `groupBy` fields (up to 1000 groups).
687
+
688
+ ```ts
689
+ const { items } = await model.aggregate<CogniteAsset>()({
690
+ viewExternalId: "CogniteAsset",
691
+ groupBy: { sourceId: true },
692
+ });
693
+
694
+ const sourceIds = items.map((row) => row.group?.sourceId);
695
+ ```
696
+
697
+ ---
698
+
699
+ ### Average volume by type
700
+
701
+ Use `avg`, `min`, `max`, or `sum` on numeric view properties. Only one aggregate operation per call.
702
+
703
+ ```ts
704
+ type PointCloudVolume = IndustrialModel<{
705
+ volume: number;
706
+ volumeType: string;
707
+ }>;
708
+
709
+ const { items } = await model.aggregate<PointCloudVolume>()({
710
+ viewExternalId: "CognitePointCloudVolume",
711
+ groupBy: { volumeType: true },
712
+ aggregate: { avg: "volume" },
713
+ });
714
+
715
+ items[0]?.group?.volumeType;
716
+ items[0]?.aggregate?.property; // "volume"
717
+ items[0]?.aggregate?.value;
718
+ ```
719
+
720
+ Other numeric aggregates:
721
+
722
+ ```ts
723
+ await model.aggregate<PointCloudVolume>()({
724
+ viewExternalId: "CognitePointCloudVolume",
725
+ aggregate: { min: "volume" },
726
+ });
727
+
728
+ await model.aggregate<PointCloudVolume>()({
729
+ viewExternalId: "CognitePointCloudVolume",
730
+ aggregate: { max: "volume" },
731
+ });
732
+
733
+ await model.aggregate<PointCloudVolume>()({
734
+ viewExternalId: "CognitePointCloudVolume",
735
+ aggregate: { sum: "volume" },
736
+ });
737
+ ```
738
+
739
+ ---
740
+
741
+ ### Count non-null values for a property
742
+
743
+ ```ts
744
+ const { items } = await model.aggregate<CogniteAsset>()({
745
+ viewExternalId: "CogniteAsset",
746
+ aggregate: { count: "name" },
747
+ });
748
+
749
+ items[0]?.aggregate?.property; // "name"
750
+ items[0]?.aggregate?.value;
751
+ ```
752
+
753
+ ---
754
+
755
+ ### Count all matching assets
756
+
757
+ A global count with no `groupBy`:
758
+
759
+ ```ts
760
+ const { items } = await model.aggregate<CogniteAsset>()({
761
+ viewExternalId: "CogniteAsset",
762
+ aggregate: { count: {} },
763
+ filters: {
764
+ OR: [{ tags: { containsAny: ["critical"] } }, { sourceId: { eq: "sap" } }],
765
+ },
766
+ });
767
+
768
+ items[0]?.aggregate?.value;
769
+ ```
770
+
771
+ ---
772
+
773
+ ### Group by a direct relation
774
+
775
+ `groupBy` supports direct relations; results are returned as `NodeId` objects.
776
+
777
+ ```ts
778
+ type PointCloudVolume = IndustrialModel<{
779
+ volume: number;
780
+ object3D?: NodeId;
781
+ }>;
782
+
783
+ const { items } = await model.aggregate<PointCloudVolume>()({
784
+ viewExternalId: "CognitePointCloudVolume",
785
+ groupBy: { object3D: true },
786
+ aggregate: { sum: "volume" },
787
+ });
788
+
789
+ items[0]?.group?.object3D?.externalId;
790
+ ```
791
+
792
+ ---
793
+
664
794
  ## API
665
795
 
666
796
  ### Exports
@@ -672,6 +802,8 @@ if (cursor) {
672
802
  | `NodeId`, `DataModelId` | Instance and data-model identifiers |
673
803
  | `QueryOptions`, `QuerySelect`, `WhereInput`, `SortInput` | Query input types |
674
804
  | `QueryResult`, `QueryResultItem`, `QueryResultMetadata` | Query output types |
805
+ | `AggregateOptions`, `AggregateGroupBy`, `AggregateDefinition` | Aggregate input types |
806
+ | `AggregateResult`, `AggregateResultItem`, `GroupByKey` | Aggregate output types |
675
807
  | `buildViewSchema`, `nodeIdSchema` | Zod schemas built from Cognite view metadata |
676
808
  | `SortDirection` | `"ascending"` \| `"descending"` |
677
809
 
@@ -737,6 +869,39 @@ items[0]?.parent?.name;
737
869
  items[0]?.externalId;
738
870
  ```
739
871
 
872
+ ### `model.aggregate<TModel>()(options)`
873
+
874
+ | Option | Type | Description |
875
+ |--------|------|-------------|
876
+ | `viewExternalId` | `string` | The view to aggregate |
877
+ | `groupBy` | `AggregateGroupBy<TModel>` | Optional. Object of groupable properties set to `true` (max 5) |
878
+ | `filters` | `WhereInput<TModel>` | Same filter syntax as `query` |
879
+ | `aggregate` | `AggregateDefinition<TModel>` | Optional. One of `avg`, `min`, `max`, `sum`, or `count` per call |
880
+
881
+ Provide at least one of `groupBy` or `aggregate`. Omit `aggregate` to fetch distinct values for the grouped fields. The client always requests nodes with `limit: 1000`.
882
+
883
+ `aggregate()` uses the same curried form as `query`. Each result item has the shape:
884
+
885
+ ```ts
886
+ type AggregateResultItem = {
887
+ group?: { /* keys from groupBy */ };
888
+ aggregate?: { property?: string; value: number };
889
+ };
890
+ ```
891
+
892
+ When counting all rows, `aggregate` has only `value` (no `property`). When aggregating a field, `property` matches the name you passed in the request.
893
+
894
+ | Aggregate | Input | Use case |
895
+ |-----------|-------|----------|
896
+ | `count` | `{ count: {} }` | Row count (optionally filtered) |
897
+ | `count` | `{ count: "name" }` | Count non-null values for a property |
898
+ | `avg` | `{ avg: "volume" }` | Average of a numeric property |
899
+ | `min` | `{ min: "volume" }` | Minimum numeric value |
900
+ | `max` | `{ max: "volume" }` | Maximum numeric value |
901
+ | `sum` | `{ sum: "volume" }` | Sum of a numeric property |
902
+
903
+ See [Count assets by source ID](#count-assets-by-source-id), [List distinct source IDs](#list-distinct-source-ids), and [Average volume by type](#average-volume-by-type) for full examples.
904
+
740
905
  ### Automatic query behavior
741
906
 
742
907
  - **`hasData` filter** — every root query includes a `hasData` constraint for the target view.