@simtlix/simfinity-js 2.0.2 → 2.2.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/AGGREGATION_CHANGES_SUMMARY.md +235 -0
- package/AGGREGATION_EXAMPLE.md +567 -0
- package/README.md +415 -3
- package/package.json +1 -1
- package/src/index.js +345 -0
- package/src/scalars.js +188 -0
- package/src/validators.js +250 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -10
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -10
- package/.github/workflows/master.yml +0 -19
- package/.github/workflows/publish.yml +0 -45
- package/.github/workflows/release.yml +0 -65
- package/BACKUP_README.md +0 -26
- package/README_INDEX_EXAMPLE.md +0 -252
- package/simtlix-simfinity-js-1.9.1.tgz +0 -0
- package/tests/objectid-indexes.test.js +0 -215
- package/tests/prevent-collection-creation.test.js +0 -67
- package/tests/scalar-naming.test.js +0 -125
- package/tests/validated-scalar.test.js +0 -172
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Aggregation Feature Implementation Summary
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Successfully added support for GraphQL aggregation queries with group by functionality to simfinity.js. This allows users to perform aggregate operations (SUM, COUNT, AVG, MIN, MAX) on entity data with flexible grouping capabilities.
|
|
5
|
+
|
|
6
|
+
## Changes Made
|
|
7
|
+
|
|
8
|
+
### 1. Custom JSON Scalar Type
|
|
9
|
+
**File:** `src/index.js`
|
|
10
|
+
- Created a custom `GraphQLJSON` scalar type for flexible JSON output in aggregation results
|
|
11
|
+
- No external dependencies required - uses only the standard GraphQL package
|
|
12
|
+
|
|
13
|
+
### 2. Core Implementation Files
|
|
14
|
+
**File:** `src/index.js`
|
|
15
|
+
|
|
16
|
+
#### Custom JSON Scalar
|
|
17
|
+
- Created a custom `GraphQLJSON` scalar type implementation
|
|
18
|
+
- Supports serialization, parsing, and literal parsing of JSON values
|
|
19
|
+
- Handles objects, arrays, strings, numbers, booleans, and null values
|
|
20
|
+
|
|
21
|
+
#### New GraphQL Types
|
|
22
|
+
|
|
23
|
+
##### QLAggregationOperation (Enum)
|
|
24
|
+
```javascript
|
|
25
|
+
const QLAggregationOperation = new GraphQLEnumType({
|
|
26
|
+
name: 'QLAggregationOperation',
|
|
27
|
+
values: {
|
|
28
|
+
SUM: { value: 'SUM' },
|
|
29
|
+
COUNT: { value: 'COUNT' },
|
|
30
|
+
AVG: { value: 'AVG' },
|
|
31
|
+
MIN: { value: 'MIN' },
|
|
32
|
+
MAX: { value: 'MAX' },
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
##### QLTypeAggregationFact (Input Type)
|
|
38
|
+
- Defines a single aggregation metric
|
|
39
|
+
- Fields:
|
|
40
|
+
- `operation` (required): The aggregation operation to perform
|
|
41
|
+
- `factName` (required): Name for the metric in the result
|
|
42
|
+
- `path` (required): Field path to aggregate (supports dot notation for related entities)
|
|
43
|
+
|
|
44
|
+
##### QLTypeAggregationExpression (Input Type)
|
|
45
|
+
- Defines the complete aggregation configuration
|
|
46
|
+
- Fields:
|
|
47
|
+
- `groupId` (required): Field path to group by (supports dot notation)
|
|
48
|
+
- `facts` (required): Array of aggregation facts to calculate
|
|
49
|
+
|
|
50
|
+
##### QLTypeAggregationResult (Output Type)
|
|
51
|
+
- Result structure for aggregation queries
|
|
52
|
+
- Fields:
|
|
53
|
+
- `groupId` (JSON): The value used for grouping
|
|
54
|
+
- `facts` (JSON): Object containing all calculated metrics
|
|
55
|
+
|
|
56
|
+
#### New Functions
|
|
57
|
+
|
|
58
|
+
##### buildFieldPath(gqltype, fieldPath)
|
|
59
|
+
- Resolves a field path string (e.g., "category" or "country.name") to MongoDB field paths
|
|
60
|
+
- Handles:
|
|
61
|
+
- Direct scalar fields
|
|
62
|
+
- Embedded object fields
|
|
63
|
+
- Non-embedded related entity fields (generates $lookup operations)
|
|
64
|
+
- Returns: `{ mongoPath, lookups }` where lookups are MongoDB aggregation stages needed
|
|
65
|
+
|
|
66
|
+
##### buildAggregationQuery(input, gqltype, aggregationExpression)
|
|
67
|
+
- Generates MongoDB aggregation pipeline for group by queries
|
|
68
|
+
- Reuses filtering logic from `buildQuery` function
|
|
69
|
+
- Process:
|
|
70
|
+
1. Applies filters (same as regular queries)
|
|
71
|
+
2. Adds lookups for related entities referenced in groupId or facts
|
|
72
|
+
3. Creates $group stage with _id set to groupId field
|
|
73
|
+
4. Adds aggregation operations for each fact
|
|
74
|
+
5. Projects final output format with groupId and facts fields
|
|
75
|
+
- Returns: Array of MongoDB aggregation pipeline stages
|
|
76
|
+
|
|
77
|
+
#### Endpoint Generation
|
|
78
|
+
**Modified:** `buildRootQuery` function
|
|
79
|
+
- For each entity type with an endpoint, automatically generates an `{entityname}_aggregate` endpoint
|
|
80
|
+
- Endpoint configuration:
|
|
81
|
+
- Inherits all filter arguments from the main query endpoint
|
|
82
|
+
- Adds required `aggregation` parameter of type `QLTypeAggregationExpression`
|
|
83
|
+
- Returns `GraphQLList(QLTypeAggregationResult)`
|
|
84
|
+
- Resolver calls `buildAggregationQuery` and executes the MongoDB aggregation pipeline
|
|
85
|
+
|
|
86
|
+
### 3. Tests
|
|
87
|
+
**File:** `tests/aggregation.test.js`
|
|
88
|
+
- Created comprehensive test suite with 5 tests
|
|
89
|
+
- Tests verify:
|
|
90
|
+
- Aggregation endpoint exists in schema
|
|
91
|
+
- Correct GraphQL type structure
|
|
92
|
+
- QLTypeAggregationResult has proper fields
|
|
93
|
+
- Filter arguments are inherited
|
|
94
|
+
- All aggregation types are present in schema
|
|
95
|
+
- Tests pass without requiring database connection (schema validation only)
|
|
96
|
+
|
|
97
|
+
### 4. Documentation
|
|
98
|
+
**File:** `AGGREGATION_EXAMPLE.md`
|
|
99
|
+
- Comprehensive usage guide with examples
|
|
100
|
+
- Covers:
|
|
101
|
+
- Basic group by with COUNT
|
|
102
|
+
- Grouping by related entity fields
|
|
103
|
+
- Multiple aggregation facts
|
|
104
|
+
- Filtering with aggregation
|
|
105
|
+
- Pagination with aggregation
|
|
106
|
+
- Field path resolution rules
|
|
107
|
+
|
|
108
|
+
## Key Features
|
|
109
|
+
|
|
110
|
+
### 1. Field Path Resolution
|
|
111
|
+
Supports multiple path formats:
|
|
112
|
+
- **Direct fields**: `"category"`, `"rating"`, `"id"`
|
|
113
|
+
- **Related entity fields**: `"country.name"`, `"studio.foundedYear"`
|
|
114
|
+
- **Nested relations**: `"country.region.name"`
|
|
115
|
+
|
|
116
|
+
### 2. Aggregation Operations
|
|
117
|
+
All standard MongoDB aggregation operations:
|
|
118
|
+
- **SUM**: Sum of numeric values
|
|
119
|
+
- **COUNT**: Count of records in group
|
|
120
|
+
- **AVG**: Average of numeric values
|
|
121
|
+
- **MIN**: Minimum value
|
|
122
|
+
- **MAX**: Maximum value
|
|
123
|
+
|
|
124
|
+
### 3. Filtering Support
|
|
125
|
+
- All filter parameters from regular queries work with aggregation
|
|
126
|
+
- Filters are applied before grouping
|
|
127
|
+
- Uses existing `buildQueryTerms` function for consistency
|
|
128
|
+
|
|
129
|
+
### 4. Automatic Lookups
|
|
130
|
+
- Automatically generates MongoDB $lookup stages for non-embedded related entities
|
|
131
|
+
- Handles complex field paths with multiple levels of relations
|
|
132
|
+
- Prevents duplicate lookups when multiple facts reference the same entity
|
|
133
|
+
|
|
134
|
+
### 5. Result Format
|
|
135
|
+
Consistent JSON output structure:
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"groupId": <value>,
|
|
139
|
+
"facts": {
|
|
140
|
+
"factName1": <calculated_value>,
|
|
141
|
+
"factName2": <calculated_value>
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## MongoDB Translation
|
|
147
|
+
|
|
148
|
+
The implementation generates efficient MongoDB aggregation pipelines:
|
|
149
|
+
|
|
150
|
+
1. **$lookup**: Joins with related entity collections
|
|
151
|
+
2. **$unwind**: Flattens joined arrays
|
|
152
|
+
3. **$match**: Applies filters
|
|
153
|
+
4. **$group**: Groups by field with aggregation operations
|
|
154
|
+
5. **$project**: Formats final output structure
|
|
155
|
+
|
|
156
|
+
## Testing Results
|
|
157
|
+
|
|
158
|
+
All tests pass successfully:
|
|
159
|
+
- ✅ 5 new aggregation tests
|
|
160
|
+
- ✅ 22 existing tests (all still passing)
|
|
161
|
+
- ✅ No linting errors
|
|
162
|
+
- ✅ No breaking changes to existing functionality
|
|
163
|
+
|
|
164
|
+
## Example Usage
|
|
165
|
+
|
|
166
|
+
### Simple Group By
|
|
167
|
+
```graphql
|
|
168
|
+
query {
|
|
169
|
+
series_aggregate(
|
|
170
|
+
aggregation: {
|
|
171
|
+
groupId: "category"
|
|
172
|
+
facts: [
|
|
173
|
+
{ operation: COUNT, factName: "total", path: "id" }
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
) {
|
|
177
|
+
groupId
|
|
178
|
+
facts
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Group By Related Entity
|
|
184
|
+
```graphql
|
|
185
|
+
query {
|
|
186
|
+
series_aggregate(
|
|
187
|
+
aggregation: {
|
|
188
|
+
groupId: "country.name"
|
|
189
|
+
facts: [
|
|
190
|
+
{ operation: COUNT, factName: "count", path: "id" }
|
|
191
|
+
{ operation: AVG, factName: "avgRating", path: "rating" }
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
) {
|
|
195
|
+
groupId
|
|
196
|
+
facts
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### With Filtering
|
|
202
|
+
```graphql
|
|
203
|
+
query {
|
|
204
|
+
series_aggregate(
|
|
205
|
+
rating: { operator: GTE, value: 8.0 }
|
|
206
|
+
aggregation: {
|
|
207
|
+
groupId: "category"
|
|
208
|
+
facts: [
|
|
209
|
+
{ operation: COUNT, factName: "highRated", path: "id" }
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
) {
|
|
213
|
+
groupId
|
|
214
|
+
facts
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Backwards Compatibility
|
|
220
|
+
|
|
221
|
+
✅ All changes are additive and non-breaking:
|
|
222
|
+
- Existing endpoints continue to work unchanged
|
|
223
|
+
- No modifications to existing input/output types
|
|
224
|
+
- Aggregation feature is opt-in (users can ignore it if not needed)
|
|
225
|
+
- All existing tests pass without modification
|
|
226
|
+
|
|
227
|
+
## Future Enhancements (Optional)
|
|
228
|
+
|
|
229
|
+
Potential improvements for future versions:
|
|
230
|
+
1. Support for multiple grouping fields
|
|
231
|
+
2. Having clause for filtering after aggregation
|
|
232
|
+
3. Support for more complex aggregation expressions
|
|
233
|
+
4. Aggregation result caching
|
|
234
|
+
5. Aggregation pagination optimization
|
|
235
|
+
|