mongodb-pipeline-builder 4.0.2 β†’ 4.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/Readme.md +374 -1962
  3. package/package.json +1 -1
package/Readme.md CHANGED
@@ -1,2143 +1,555 @@
1
- ++<div style="text-align: center; width: 100%;">
2
-
3
- <div style="display: inline-block">
1
+ <div align="center">
4
2
 
5
3
  [![NPM version](https://img.shields.io/npm/v/mongodb-pipeline-builder.svg)](https://www.npmjs.com/package/mongodb-pipeline-builder)
6
4
  ![NPM](https://img.shields.io/npm/l/mongodb-pipeline-builder?registry_uri=https%3A%2F%2Fregistry.npmjs.com)
7
5
  ![npm](https://img.shields.io/npm/dw/mongodb-pipeline-builder)
8
- </div>
9
-
10
- <div style="display: inline-block">
11
6
 
12
7
  ![GitHub branch checks state](https://img.shields.io/github/checks-status/MikeDev75015/mongodb-pipeline-builder/main)
13
8
  [![CircleCI](https://circleci.com/gh/MikeDev75015/mongodb-pipeline-builder.svg?style=shield)](https://app.circleci.com/pipelines/github/MikeDev75015/mongodb-pipeline-builder)
14
9
  ![Sonar Quality Gate](https://img.shields.io/sonar/quality_gate/MikeDev75015_mongodb-pipeline-builder?server=https%3A%2F%2Fsonarcloud.io)
15
- </div>
16
- </div>
17
-
18
- <div style="text-align: center; width: 100%;">
19
- <div style="display: inline-block">
20
10
 
21
11
  ![Sonar Tests](https://img.shields.io/sonar/tests/MikeDev75015_mongodb-pipeline-builder?server=https%3A%2F%2Fsonarcloud.io)
22
12
  ![Sonar Coverage](https://img.shields.io/sonar/coverage/MikeDev75015_mongodb-pipeline-builder?server=https%3A%2F%2Fsonarcloud.io)
23
13
  <img src="https://mikedev75015.github.io/mongodb-pipeline-builder/images/coverage-badge-documentation.svg" alt="documentation-badge">
24
- </div>
25
-
26
- <div style="display: inline-block">
27
-
28
- ![GitHub top language](https://img.shields.io/github/languages/top/MikeDev75015/mongodb-pipeline-builder)
29
- [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=MikeDev75015_mongodb-pipeline-builder&metric=ncloc)](https://sonarcloud.io/dashboard?id=MikeDev75015_mongodb-pipeline-builder)
30
- [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=MikeDev75015_mongodb-pipeline-builder&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=MikeDev75015_mongodb-pipeline-builder)
31
- </div>
32
- </div>
33
-
34
- <div style="text-align: center; width: 100%;">
35
- <div style="display: inline-block">
36
-
37
- ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/MikeDev75015/mongodb-pipeline-builder)
38
- ![GitHub commit activity](https://img.shields.io/github/commit-activity/w/MikeDev75015/mongodb-pipeline-builder)
39
- ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/MikeDev75015/mongodb-pipeline-builder/main)
40
- </div>
41
-
42
- <div style="display: inline-block">
43
14
 
44
15
  [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=MikeDev75015_mongodb-pipeline-builder&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=MikeDev75015_mongodb-pipeline-builder)
45
16
  [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=MikeDev75015_mongodb-pipeline-builder&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=MikeDev75015_mongodb-pipeline-builder)
46
17
  [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=MikeDev75015_mongodb-pipeline-builder&metric=security_rating)](https://sonarcloud.io/dashboard?id=MikeDev75015_mongodb-pipeline-builder)
47
- </div>
48
- </div>
49
18
 
50
19
  ---
51
20
 
52
- <div style="text-align: center; width: 100%;">
53
-
54
- [-> Technical documentation <-](https://mikedev75015.github.io/mongodb-pipeline-builder)
21
+ [πŸ“š Technical Documentation](https://mikedev75015.github.io/mongodb-pipeline-builder)
55
22
 
23
+ # MongoDB Pipeline Builder
56
24
 
57
-
58
- # mongodb-pipeline-builder
25
+ **A type-safe, fluent API for building MongoDB aggregation pipelines**
59
26
 
60
27
  </div>
61
28
 
29
+ ## πŸš€ Overview
62
30
 
63
- <p style="text-align: justify; width: 100%;font-size: 15px;">
64
-
65
- **mongodb-pipeline-builder** is a pipeline builder for the [db.collection.aggregate](https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/), the [db.aggregate](https://www.mongodb.com/docs/v7.0/reference/method/db.aggregate/) and the mongoose [Model.aggregate](https://mongoosejs.com/docs/api/aggregate.html#Aggregate()) methods.
31
+ **mongodb-pipeline-builder** is a powerful TypeScript library that simplifies the creation of MongoDB aggregation pipelines. It provides a fluent, type-safe API that makes your aggregation pipelines more readable, maintainable, and less error-prone.
66
32
 
67
- - Simplify pipelines by making them more readable
68
- - Pipelines are easier to edit.
69
- - Pipeline stages appear in an array.
70
- - Sequential stages for documents
71
-
72
- All stages except the Out, Merge, GeoNear, ChangeStream, ChangeStreamSplitLargeEvent and Paging stages can appear multiple times in a pipeline.
73
-
74
- </p>
75
-
76
- ---
33
+ ### Key Features
77
34
 
78
- ## npm package <img src="https://pbs.twimg.com/media/EDoWJbUXYAArclg.png" width="24" height="24" />
35
+ ✨ **Type-Safe** - Full TypeScript support with generics for typed responses
36
+ πŸ“– **Readable** - Fluent API that makes complex pipelines easy to understand
37
+ πŸ”§ **Maintainable** - Modular design with reusable helpers
38
+ 🎯 **Complete** - Supports all MongoDB aggregation stages and operators
39
+ ⚑ **Efficient** - Built-in pagination support with optimized queries
40
+ πŸ›‘οΈ **Validated** - Automatic validation of pipeline stages
79
41
 
80
- `npm i -S mongodb-pipeline-builder`
42
+ ### Supported Platforms
81
43
 
44
+ - βœ… [MongoDB Native Driver](https://www.mongodb.com/docs/drivers/node/current/) - `db.collection.aggregate()`
45
+ - βœ… [MongoDB Database Commands](https://www.mongodb.com/docs/manual/reference/method/db.aggregate/) - `db.aggregate()`
46
+ - βœ… [Mongoose](https://mongoosejs.com/) - `Model.aggregate()`
82
47
 
83
48
  ---
84
49
 
50
+ ## πŸ“¦ Installation
85
51
 
86
- ### **News and Breaking changes** between **v3** and **v4**
87
-
88
- #### **PipelineBuilder:**
89
- * Renaming `getPipeline()` with `build()`
90
- * Added new stages: `ChangeStream`, `ChangeStreamSplitLargeEvent`, `Densify`, `Documents`, `Fill`, `ListLocalSessions`, `ListSampledQueries`, `ListSearchIndexes`, `SearchMeta`, `SetWindowFields` and `ShardedDataDistribution`.
91
- * Added the possibility to insert stages without validation with new `Insert` stage.
92
- * Checking for non-duplicable stages.
93
-
94
- #### **Helpers:**
95
- * Replacing the `Payload` suffix with `Helper` suffix
96
- * Prefixed with the name of the pipeline stage where they should be used
97
-
98
- #### **Operators:**
99
- * Prefixed with the **$** symbol
100
- * Rename `MapOperator` to `$Map`
101
-
102
-
103
- #### **GetResult:**
104
- * To be used if no Paging stage is set
105
- * Removing GetDocs method arguments
106
- * Added new GetElement method to the response object
107
-
108
- #### **GetPagingResult:**
109
- * To be used exclusively with Paging stage.
52
+ ```bash
53
+ npm install mongodb-pipeline-builder
54
+ ```
110
55
 
56
+ ```bash
57
+ yarn add mongodb-pipeline-builder
58
+ ```
111
59
 
112
- *Welcome generics! `GetResult<Type>` and `GetPagingResult<Type>` now offer the ability to type responses.*
60
+ ```bash
61
+ pnpm add mongodb-pipeline-builder
62
+ ```
113
63
 
114
64
  ---
115
65
 
116
- ## Usage:
117
-
118
-
119
- ### Using `require()`
120
-
121
- ```typescript
122
- const PipelineBuilder = require("mongodb-pipeline-builder").PipelineBuilder;
123
- const { LookupEqualityHelper, ProjectOnlyHelper, Field } = require('mongodb-pipeline-builder/helpers');
124
- const { $LessThanEqual, $ArrayElementAt, $Equal, $Expression } = require('mongodb-pipeline-builder/operators');
125
- ```
126
-
127
- ### Using `import`
66
+ ## 🎯 Quick Start
128
67
 
68
+ ### Basic Example
129
69
 
130
70
  ```typescript
131
71
  import { PipelineBuilder } from 'mongodb-pipeline-builder';
132
- import { LookupEqualityHelper, ProjectOnlyHelper, Field } from 'mongodb-pipeline-builder/helpers';
133
- import { $LessThanEqual, $ArrayElementAt, $Equal, $Expression } from 'mongodb-pipeline-builder/operators';
134
- ```
72
+ import { ProjectOnlyHelper } from 'mongodb-pipeline-builder/helpers';
73
+ import { $Expression, $Equal } from 'mongodb-pipeline-builder/operators';
135
74
 
136
- ---
137
-
138
- ## Pagination example
75
+ const pipeline = new PipelineBuilder('users-query')
76
+ .Match($Expression($Equal('$status', 'active')))
77
+ .Project(ProjectOnlyHelper('name', 'email', 'createdAt'))
78
+ .Sort({ createdAt: -1 })
79
+ .Limit(10)
80
+ .build();
139
81
 
82
+ // Use with MongoDB
83
+ const results = await db.collection('users').aggregate(pipeline).toArray();
140
84
 
141
- ```typescript
142
- const myNewPipeline = new PipelineBuilder( 'myPagination', { debug: true } )
143
- .Match( $Expression( $LessThanEqual( '$id', 20 ) ) )
144
- .Project( ProjectOnlyHelper( 'name', 'weight' ) )
145
- .Paging( 5, 3 ) // 5 per page, page 3
146
- .build();
85
+ // Use with Mongoose
86
+ const results = await User.aggregate(pipeline);
147
87
  ```
148
88
 
149
- *is equivalent to*
150
-
89
+ ### With Pagination
151
90
 
152
91
  ```typescript
153
- const myNewPipeline = [ {
154
- $facet: {
155
- docs: [
156
- { $match: { $expr: { $lte: ["$id", 20] } } },
157
- { $project: { _id: 0, name: 1, weight: 1 } },
158
- { $skip: 10 },
159
- { $limit: 5 }
160
- ],
161
- count: [
162
- { $match: { $expr: { $lte: ["$id", 20] } } },
163
- { $count: "totalElements" }
164
- ]
165
- }
166
- } ];
167
- ```
92
+ import { PipelineBuilder, GetPagingResult } from 'mongodb-pipeline-builder';
93
+ import { $Expression, $GreaterThan } from 'mongodb-pipeline-builder/operators';
168
94
 
169
- ---
95
+ const pipeline = new PipelineBuilder('paginated-users')
96
+ .Match($Expression($GreaterThan('$age', 18)))
97
+ .Sort({ createdAt: -1 })
98
+ .Paging(20, 1) // 20 items per page, page 1
99
+ .build();
170
100
 
171
- ## No pagination example
101
+ const result = await GetPagingResult(User, pipeline);
172
102
 
173
- ```typescript
174
- const myNewPipeline = new PipelineBuilder( 'user-skills' )
175
- .Match( $Expression( $Equal( '$id', 123456 ) ) )
176
- .Lookup( LookupEqualityHelper( 'profiles', 'profile', 'id', 'profileId' ) )
177
- .Project( ProjectOnlyHelper( 'firstname', 'lastname', 'email' ) )
178
- .AddFields(
179
- Field( 'skills', $ArrayElementAt( '$profile.skills', 0 ) ),
180
- Field( 'availability', $ArrayElementAt( '$profile.availability', 0 ) )
181
- )
182
- .Unset( 'profile' )
183
- .build();
103
+ console.log(result.GetDocs()); // Document array
104
+ console.log(result.GetCount()); // Total count
105
+ console.log(result.GetTotalPageNumber()); // Total pages
184
106
  ```
185
107
 
186
- *is equivalent to*
108
+ ### With Lookups (Joins)
187
109
 
188
110
  ```typescript
189
- const myNewPipeline = [
190
- { $match: { $expr: { $eq: ["$id", 123456] } } },
191
- { $lookup: { from: "profiles", as: "profile", localField: "id", foreignField: "profileId" } },
192
- { $project: { _id: 0, firstname: 1, lastname: 1, email: 1 } },
193
- { $addFields: {
194
- skills: { $arrayElemAt: ["$profile.skills", 0] },
195
- availability: { $arrayElemAt: ["$profile.availability", 0] }
196
- } },
197
- { $unset: "profile" }
198
- ];
199
- ```
200
-
201
- ___
202
-
203
- # GetResult method (No pagination)
111
+ import { PipelineBuilder } from 'mongodb-pipeline-builder';
112
+ import { LookupEqualityHelper, Field } from 'mongodb-pipeline-builder/helpers';
113
+ import { $ArrayElementAt } from 'mongodb-pipeline-builder/operators';
204
114
 
205
- ```typescript
206
- GetResult<T>(): Promise<GetResultResponse<T>>
115
+ const pipeline = new PipelineBuilder('users-with-profiles')
116
+ .Lookup(LookupEqualityHelper('profiles', 'profile', 'profileId', '_id'))
117
+ .AddFields(
118
+ Field('profileData', $ArrayElementAt('$profile', 0))
119
+ )
120
+ .Unset('profile')
121
+ .build();
207
122
  ```
208
123
 
209
- <p style="font-size: 15px;">
210
-
211
- `GetResult<T>()` is an **asynchronous** method that provides a very easy way to use aggregation responses.
212
-
213
- <p>
214
-
215
-
216
- <p style="font-size: 15px;">
217
-
218
- This method returns a `GetResultResponse` object that contains 3 methods:<br>
219
-
220
- - `GetDocs(): T[]` to get all the documents that match the request.
221
- - `GetElement(index: number | 'last'): T` to get a particular document by its index.
222
- - `GetCount(): number` to get the total number of documents found.
223
-
224
- </p>
124
+ ---
225
125
 
126
+ ## πŸ“š Documentation
226
127
 
227
- ```typescript
228
- const result = await GetResult<DocType>( target, pipeline );
229
- result.GetDocs(); // () => DocType[]
230
- result.GetElement(index | 'last'); // () => DocType | undefined
231
- result.GetCount(); // () => number
232
- ```
128
+ ### Core Concepts
233
129
 
234
- *$Or*
235
- ```typescript
236
- GetResult<DocType>( target, pipeline ).then( result => {
237
- result.GetDocs(); // () => DocType[]
238
- result.GetElement(index | 'last'); // () => DocType | undefined
239
- result.GetCount(); // () => number
240
- } );
241
- ```
130
+ - **[Getting Started Guide](./docs/getting-started.md)** - Detailed introduction and setup
131
+ - **[Migration Guide v3 β†’ v4](./docs/migration-guide.md)** - Upgrade from version 3
242
132
 
243
- ### `GetElement(index: number | 'last')` method possibilities:
133
+ ### API Reference
244
134
 
245
- <p style="font-size: 15px;">
135
+ - **[Pipeline Stages](./docs/api/stages.md)** - All MongoDB aggregation stages
136
+ - **[Operators](./docs/api/operators.md)** - Aggregation operators ($match, $group, etc.)
137
+ - **[Helpers](./docs/api/helpers.md)** - Utility functions and stage helpers (Field, ProjectHelper, LookupHelper, etc.)
246
138
 
247
- - A particular document can be retrieved by specifying its index.
248
- - To get the last document, simply provide the string `'last'`.
249
- - If the specified index is greater than the index of the last document, `GetElement()` will return undefined.
250
- </p>
139
+ ### Examples & Tutorials
251
140
 
252
- ```typescript
253
- // GetDocs() -> [document1, document2, document3, ..., document51]
254
- result.GetElement(2); // will return document to index 2, document3
255
- result.GetElement('last'); // will return the last document, document51
256
- result.GetElement(99); // will return undefined
257
- ```
141
+ - **[Pagination Examples](./docs/examples/pagination.md)** - Implementing pagination patterns
142
+ - **[Lookup & Join Examples](./docs/examples/lookups.md)** - Working with multiple collections
258
143
 
259
144
  ---
260
145
 
261
- # GetPagingResult method (Pagination)
262
-
263
- ```typescript
264
- GetPagingResult<T>(): Promise<GetPagingResultResponse<T>>
265
- ```
146
+ ## πŸ”₯ What's New in v4
266
147
 
267
- <p style="font-size: 15px;">
148
+ ### Breaking Changes
268
149
 
269
- `GetPagingResult<T>()` is an **asynchronous** method that provides a very easy way to use aggregation responses when **Paging** stage is used.
150
+ #### PipelineBuilder
151
+ - ✨ `build()` replaces `getPipeline()`
152
+ - πŸ†• New stages: `ChangeStream`, `ChangeStreamSplitLargeEvent`, `Densify`, `Documents`, `Fill`, `ListLocalSessions`, `ListSampledQueries`, `ListSearchIndexes`, `SearchMeta`, `SetWindowFields`, `ShardedDataDistribution`
153
+ - πŸ†• `Insert()` stage for adding custom stages without validation
154
+ - βœ… Automatic detection of non-duplicable stages
270
155
 
271
- <p>
156
+ #### Helpers
157
+ - πŸ”„ `Payload` suffix β†’ `Helper` suffix
158
+ - 🏷️ Prefixed with stage name (e.g., `LookupEqualityHelper`)
272
159
 
160
+ #### Operators
161
+ - 🏷️ All operators prefixed with `$` (e.g., `$Add`, `$Match`)
162
+ - πŸ”„ `MapOperator` β†’ `$Map`
273
163
 
274
- <p style="font-size: 15px;">
164
+ #### Result Methods
165
+ - 🎯 `GetResult<T>()` - For non-paginated queries
166
+ - ✨ `GetElement(index | 'last')` - New method to get specific document
167
+ - πŸš€ Generic type support for typed responses
168
+ - 🎯 `GetPagingResult<T>()` - Exclusively for paginated queries
169
+ - πŸš€ Generic type support for typed responses
275
170
 
276
- This method returns a `GetPagingResultResponse` object that contains three methods:
277
- - `GetDocs()` to get the documents found.
278
- - `GetCount()` to get the total number of documents found.
279
- - `GetTotalPageNumber()` to get the total number of pages.
280
-
281
- </p>
171
+ ---
282
172
 
173
+ ## πŸ’‘ Real-World Example
174
+
175
+ ```typescript
176
+ import { PipelineBuilder, GetResult } from 'mongodb-pipeline-builder';
177
+ import {
178
+ LookupEqualityHelper,
179
+ ProjectOnlyHelper,
180
+ Field
181
+ } from 'mongodb-pipeline-builder/helpers';
182
+ import {
183
+ $Expression,
184
+ $And,
185
+ $Equal,
186
+ $GreaterThanEqual,
187
+ $ArrayElementAt
188
+ } from 'mongodb-pipeline-builder/operators';
189
+
190
+ // Complex query: Active users with their orders
191
+ const pipeline = new PipelineBuilder('active-users-with-orders', { debug: true })
192
+ // Filter active users over 18
193
+ .Match($Expression(
194
+ $And(
195
+ $Equal('$status', 'active'),
196
+ $GreaterThanEqual('$age', 18)
197
+ )
198
+ ))
199
+
200
+ // Join with orders collection
201
+ .Lookup(LookupEqualityHelper('orders', 'orders', '_id', 'userId'))
202
+
203
+ // Project specific fields
204
+ .Project(ProjectOnlyHelper('name', 'email', 'age'))
205
+
206
+ // Add computed fields
207
+ .AddFields(
208
+ Field('totalOrders', { $size: '$orders' }),
209
+ Field('lastOrder', $ArrayElementAt('$orders', -1))
210
+ )
211
+
212
+ // Sort by total orders descending
213
+ .Sort(Field('totalOrders', -1))
214
+
215
+ // Limit results
216
+ .Limit(50)
217
+
218
+ .build();
219
+
220
+ // Execute query with typed response
221
+ interface UserWithOrders {
222
+ name: string;
223
+ email: string;
224
+ age: number;
225
+ totalOrders: number;
226
+ lastOrder?: any;
227
+ }
283
228
 
284
- ```typescript
285
- const result = await GetPagingResult<DocType>(target, pipeline);
286
- result.GetDocs(); // () => DocType[]
287
- result.GetCount(); // () => number
288
- result.GetTotalPageNumber(); // () => number
289
- ```
229
+ const result = await GetResult<UserWithOrders>(User, pipeline);
290
230
 
291
- *$Or*
292
- ```typescript
293
- GetPagingResult<DocType>(target, pipeline).then( result => {
294
- result.GetDocs(); // () => DocType[]
295
- result.GetCount(); // () => number
296
- result.GetTotalPageNumber(); // () => number
297
- } );
231
+ // Access results
232
+ const users = result.GetDocs(); // UserWithOrders[]
233
+ const count = result.GetCount(); // number
234
+ const firstUser = result.GetElement(0); // UserWithOrders | undefined
235
+ const lastUser = result.GetElement('last'); // UserWithOrders | undefined
298
236
  ```
299
237
 
238
+ ---
300
239
 
301
- ___
302
-
240
+ ## πŸ§ͺ Try It Online
303
241
 
304
- [=> Try the lib on NPM RunKit with the require method <=](https://npm.runkit.com/mongodb-pipeline-builder)
242
+ [β†’ Try the library on NPM RunKit](https://npm.runkit.com/mongodb-pipeline-builder)
305
243
 
306
244
  ---
307
245
 
308
- `// builder = new PipelineBuilder('example');`
246
+ ## πŸ“Š Comparison: Before & After
309
247
 
310
- ## CUSTOM STAGES
311
-
312
- ### Paging(elementsPerPage, page)
313
-
314
- *The Paging stage automatically adds 3 native stages used to paginate documents ($skip, $limit and $count).
315
- <br>Page is optional and defaults to 1.*
248
+ ### Before (Raw MongoDB)
316
249
 
317
250
  ```typescript
318
- builder.Paging(5, 2).build();
319
-
320
- // pipeline
321
- [
251
+ const pipeline = [
252
+ {
253
+ $match: {
254
+ $expr: {
255
+ $and: [
256
+ { $eq: ["$status", "active"] },
257
+ { $gte: ["$age", 18] }
258
+ ]
259
+ }
260
+ }
261
+ },
322
262
  {
323
- $facet: {
324
- docs: [ { '$skip': 5 }, { '$limit': 5 } ],
325
- count: [ { '$count': 'totalElements' } ]
263
+ $lookup: {
264
+ from: "orders",
265
+ localField: "_id",
266
+ foreignField: "userId",
267
+ as: "orders"
326
268
  }
327
- }
328
- ]
329
- ```
330
-
331
- ### Insert(stage)
332
-
333
- *The Insert stage allows you to insert a stage without validation.
334
- <br>Usefully when you need to insert a stage that is not yet implemented
335
- or when the value fails validation but for some reason you want to keep it.*
336
-
337
- ```typescript
338
- builder.Insert({ '$myCustomStage': { myField: 'myValue' } }).build();
339
-
340
- // pipeline
341
- [ { $myCustomStage: { myField: 'myValue' } } ]
342
- ```
343
-
344
-
345
- ## [MONGODB STAGES](https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/)
346
-
347
- ### [AddFields](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addFields/)(...values)
348
- #### Helper: `Field(name, value)`
349
- ```typescript
350
- builder.AddFields(
351
- Field('foo', 'value1'),
352
- Field('bar', 'value2'),
353
- ).build();
354
-
355
- // pipeline
356
- [ { $addFields: { foo: 'value1', bar: 'value2' } } ]
357
- ```
358
-
359
- ### [Bucket](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket/)(value)
360
- #### Helper: `BucketHelper(groupBy, boundaries, optional)`
361
- ```typescript
362
- builder.Bucket(BucketHelper('$age', [6, 13, 18])).build();
363
-
364
- // pipeline
365
- [ { $bucket: { groupBy: '$age', boundaries: [ 6, 13, 18 ] } } ]
366
- ```
367
-
368
- ### [BucketAuto](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketAuto/)(value)
369
- #### Helper: `BucketAutoHelper(groupBy, buckets, optional)`
370
- ```typescript
371
- builder.BucketAuto(BucketAutoHelper('$age', 5)).build();
372
-
373
- // pipeline
374
- [ { $bucketAuto: { groupBy: '$age', buckets: 5 } } ]
375
- ```
376
-
377
- ### [ChangeStream](https://www.mongodb.com/docs/manual/reference/operator/aggregation/changeStream/)(value)
378
- #### Helper: `ChangeStreamHelper(optional)`
379
- ```typescript
380
- builder.ChangeStream(ChangeStreamHelper()).build();
381
-
382
- // pipeline
383
- [ { $changeStream: {} } ]
384
- ```
385
-
386
- ### [ChangeStreamSplitLargeEvent](https://www.mongodb.com/docs/manual/reference/operator/aggregation/changeStreamSplitLargeEvent/)()
387
- ```typescript
388
- builder.ChangeStreamSplitLargeEvent().build();
389
-
390
- // pipeline
391
- [ { $changeStreamSplitLargeEvent: {} } ]
392
- ```
393
-
394
- ### [CollStats](https://www.mongodb.com/docs/manual/reference/operator/aggregation/collStats/)(value)
395
- #### Helper: `CollStatsHelper(optional)`
396
- ```typescript
397
- builder.CollStats(CollStatsHelper()).build();
398
-
399
- // pipeline
400
- [ { $collStats: {} } ]
401
- ```
402
-
403
- ### [Count](https://www.mongodb.com/docs/manual/reference/operator/aggregation/count/)(value)
404
- ```typescript
405
- builder.Count('counter').build();
406
-
407
- // pipeline
408
- [ { $count: 'counter' } ]
269
+ },
270
+ {
271
+ $project: {
272
+ _id: 0,
273
+ name: 1,
274
+ email: 1,
275
+ age: 1,
276
+ totalOrders: { $size: "$orders" },
277
+ lastOrder: { $arrayElemAt: ["$orders", -1] }
278
+ }
279
+ },
280
+ { $sort: { totalOrders: -1 } },
281
+ { $limit: 50 }
282
+ ];
409
283
  ```
410
284
 
411
- ### [CurrentOp](https://www.mongodb.com/docs/manual/reference/operator/aggregation/currentOp/)(value)
412
- #### Helper: `CurrentOpHelper(optional)`
413
- ```typescript
414
- builder.CurrentOp(CurrentOpHelper()).build();
415
-
416
- // pipeline
417
- [ { $currentOp: {} } ]
418
- ```
285
+ ### After (With Pipeline Builder)
419
286
 
420
- ### [Densify](https://www.mongodb.com/docs/manual/reference/operator/aggregation/densify/)(value)
421
- #### Helper: `DensifyHelper(field, range, optional)`
422
287
  ```typescript
423
- builder.Densify(
424
- DensifyHelper(
425
- 'altitude',
426
- { bounds: 'full', step: 200 },
427
- { partitionByFields: [ 'variety' ] }
428
- ),
429
- ).build();
430
-
431
- // pipeline
432
- [
433
- {
434
- $densify: {
435
- field: 'altitude',
436
- range: { bounds: 'full', step: 200 }
437
- partitionByFields: [ 'variety' ],
438
- }
439
- }
440
- ]
288
+ const pipeline = new PipelineBuilder('active-users')
289
+ .Match($Expression($And(
290
+ $Equal('$status', 'active'),
291
+ $GreaterThanEqual('$age', 18)
292
+ )))
293
+ .Lookup(LookupEqualityHelper('orders', 'orders', '_id', 'userId'))
294
+ .Project(
295
+ ProjectOnlyHelper('name', 'email', 'age'),
296
+ Field('totalOrders', { $size: '$orders' }),
297
+ Field('lastOrder', $ArrayElementAt('$orders', -1))
298
+ )
299
+ .Sort(Field('totalOrders', -1))
300
+ .Limit(50)
301
+ .build();
441
302
  ```
442
303
 
443
- ### [Documents](https://www.mongodb.com/docs/manual/reference/operator/aggregation/documents/)(...values)
444
- ```typescript
445
- builder.Documents({ docId: 1 }, { docId: 2 }, { docId: 3 }).build();
304
+ ---
446
305
 
447
- // pipeline
448
- [ { $documents: [ { docId: 1 }, { docId: 2 }, { docId: 3 } ] } ]
449
- ```
306
+ ## πŸ” Working with Results
450
307
 
451
- ### [Facet](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet/)(...values)
452
- #### Helper: `Field(name, pipeline)`
453
- ```typescript
454
- builder.Facet(
455
- Field('pipeline1', [{ $match: { tag: 'first' }}]),
456
- Field('pipeline2', [{ $match: { tag: 'second' }}]),
457
- Field('pipeline3', [{ $match: { tag: 'third' }}]),
458
- ).build();
459
-
460
- // pipeline
461
- [
462
- {
463
- $facet: {
464
- pipeline1: [ { '$match': { tag: 'first' } } ],
465
- pipeline2: [ { '$match': { tag: 'second' } } ],
466
- pipeline3: [ { '$match': { tag: 'third' } } ]
467
- }
468
- }
469
- ]
470
- ```
308
+ ### GetResult<T> - For Non-Paginated Queries
471
309
 
472
- ### [Fill](https://www.mongodb.com/docs/manual/reference/operator/aggregation/fill/)(value)
473
- #### Helper: `FillHelper(output, optional)`
474
- ```typescript
475
- builder.Fill(
476
- FillHelper({
477
- bootsSold: { value: 0 },
478
- sandalsSold: { value: 0 },
479
- sneakersSold: { value: 0 },
480
- }),
481
- ).build();
482
-
483
- // pipeline
484
- [
485
- {
486
- $fill: {
487
- output: {
488
- bootsSold: { value: 0 },
489
- sandalsSold: { value: 0 },
490
- sneakersSold: { value: 0 }
491
- }
492
- }
493
- }
494
- ]
495
- ```
310
+ Use when your pipeline does **not** include the `Paging` stage:
496
311
 
497
- ### [GeoNear](https://www.mongodb.com/docs/manual/reference/operator/aggregation/geoNear/)(value)
498
- #### Helper: `GeoNearHelper(near, distanceField, optional)`
499
312
  ```typescript
500
- builder.GeoNear(
501
- GeoNearHelper({ type: "Point", coordinates: [ -73.99279 , 40.719296 ] }, 'calculated')
502
- ).build();
503
-
504
- // pipeline
505
- [
506
- {
507
- $geoNear: {
508
- near: { type: 'Point', coordinates: [ -73.99279, 40.719296 ] },
509
- distanceField: 'calculated'
510
- }
511
- }
512
- ]
513
- ```
313
+ import { GetResult } from 'mongodb-pipeline-builder';
514
314
 
515
- ### [GraphLookup](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphLookup/)(value)
516
- ```typescript
517
- builder.GraphLookup({
518
- from: 'employees', startWith: '$reportsTo', connectFromField: 'reportsTo', connectToField: 'name', as: 'reportingHierarchy',
519
- }).build();
315
+ interface User {
316
+ name: string;
317
+ email: string;
318
+ age: number;
319
+ }
520
320
 
521
- // pipeline
522
- [
523
- {
524
- $graphLookup: {
525
- from: 'employees',
526
- startWith: '$reportsTo',
527
- connectFromField: 'reportsTo',
528
- connectToField: 'name',
529
- as: 'reportingHierarchy'
530
- }
531
- }
532
- ]
533
- ```
321
+ const pipeline = new PipelineBuilder('users')
322
+ .Match($Expression($Equal('$status', 'active')))
323
+ .build();
534
324
 
535
- ### [Group](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group/)(value)
536
- ```typescript
537
- builder.Group({ _id: null, count: { $count: { } } }).build();
325
+ const result = await GetResult<User>(User, pipeline);
538
326
 
539
- // pipeline
540
- [
541
- { $group: { _id: null, count: { '$count': {} } } }
542
- ]
327
+ const users = result.GetDocs(); // User[] - all documents
328
+ const count = result.GetCount(); // number - total count
329
+ const firstUser = result.GetElement(0); // User | undefined
330
+ const lastUser = result.GetElement('last'); // User | undefined
543
331
  ```
544
332
 
545
- ### [IndexStats](https://www.mongodb.com/docs/manual/reference/operator/aggregation/indexStats/)()
546
- ```typescript
547
- builder.IndexStats().build();
548
-
549
- // pipeline
550
- [ { $indexStats: {} } ]
551
- ```
333
+ ---
552
334
 
553
- ### [Limit](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit/)(value)
554
- ```typescript
555
- builder.Limit(10).build();
335
+ ### GetPagingResult<T> - For Paginated Queries
556
336
 
557
- // pipeline
558
- [ { $limit: 10 } ]
559
- ```
337
+ Use **exclusively** when your pipeline includes the `Paging` stage:
560
338
 
561
- ### [ListLocalSessions](https://www.mongodb.com/docs/manual/reference/operator/aggregation/listLocalSessions/)(value)
562
339
  ```typescript
563
- builder.ListLocalSessions({ allUsers: true }).build();
340
+ import { GetPagingResult } from 'mongodb-pipeline-builder';
564
341
 
565
- // pipeline
566
- [ { $listLocalSessions: { allUsers: true } } ]
567
- ```
342
+ const pipeline = new PipelineBuilder('users')
343
+ .Match($Expression($Equal('$status', 'active')))
344
+ .Paging(20, 1) // Required for GetPagingResult
345
+ .build();
568
346
 
569
- ### [ListSampledQueries](https://www.mongodb.com/docs/manual/reference/operator/aggregation/listSampledQueries/)(value)
570
- ```typescript
571
- builder.ListSampledQueries({ namespace: "social.post" }).build();
347
+ const result = await GetPagingResult<User>(User, pipeline);
572
348
 
573
- // pipeline
574
- [ { $listSampledQueries: { namespace: 'social.post' } } ]
349
+ const users = result.GetDocs(); // User[] - current page
350
+ const totalCount = result.GetCount(); // number - total documents
351
+ const totalPages = result.GetTotalPageNumber(); // number - total pages
575
352
  ```
576
353
 
577
- ### [ListSearchIndexes](https://www.mongodb.com/docs/manual/reference/operator/aggregation/listSearchIndexes/)(value)
578
- ```typescript
579
- builder.ListSearchIndexes({ name: 'searchIndex01' }).build();
354
+ > πŸ“– **Learn More:** See [Getting Started Guide](./docs/getting-started.md) for detailed examples
580
355
 
581
- // pipeline
582
- [ { $listSearchIndexes: { name: 'searchIndex01' } } ]
583
- ```
356
+ ---
584
357
 
585
- ### [ListSessions](https://www.mongodb.com/docs/manual/reference/operator/aggregation/listSessions/)(value)
586
- ```typescript
587
- builder.ListSessions({ allUsers: true }).build();
358
+ ## πŸ“š API Reference Quick Links
588
359
 
589
- // pipeline
590
- [ { $listSessions: { allUsers: true } } ]
591
- ```
360
+ ### Pipeline Stages
592
361
 
593
- ### [Lookup](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/)(value)
594
- #### Helper: `LookupConditionHelper(from, as, optional)`
595
- ```typescript
596
- builder.Lookup(LookupConditionHelper('users', 'users')).build();
362
+ All MongoDB aggregation stages are supported. See [complete reference](./docs/api/stages.md).
597
363
 
598
- // pipeline
599
- [ { $lookup: { from: 'users', as: 'users' } } ]
600
- ```
601
- #### Helper: `LookupEqualityHelper(from, as, localField, foreignField)`
602
- ```typescript
603
- builder.Lookup(
604
- LookupEqualityHelper('users', 'users', 'userId', 'id')
605
- ).build();
364
+ **Common Stages:**
365
+ - `Match()` - Filter documents
366
+ - `Project()` - Select/transform fields
367
+ - `Group()` - Group and aggregate
368
+ - `Sort()` - Sort documents
369
+ - `Limit()` - Limit results
370
+ - `Lookup()` - Join collections
371
+ - `Unwind()` - Deconstruct arrays
372
+ - `AddFields()` - Add computed fields
373
+ - `Paging()` - Add pagination
606
374
 
607
- // pipeline
608
- [
609
- {
610
- $lookup: {
611
- from: 'users',
612
- localField: 'userId',
613
- foreignField: 'id',
614
- as: 'users'
615
- }
616
- }
617
- ]
618
- ```
375
+ ### Operators
619
376
 
620
- ### [Match](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match/)(value)
621
- #### Helper: `Field(name, value)`
622
- ```typescript
623
- builder.Match(Field('age', 18)).build();
377
+ 100+ MongoDB operators supported. See [complete reference](./docs/api/operators.md).
624
378
 
625
- // pipeline
626
- [ { $match: { age: 18 } } ]
627
- ```
628
- #### Operator: `$Expression`
629
- ```typescript
630
- builder.Match($Expression($GreaterThanEqual('$age', 18))).build();
379
+ **Common Operators:**
380
+ - Comparison: `$Equal`, `$GreaterThan`, `$LessThan`
381
+ - Logical: `$And`, `$Or`, `$Not`
382
+ - Arithmetic: `$Add`, `$Subtract`, `$Multiply`, `$Divide`
383
+ - Array: `$Size`, `$Filter`, `$Map`, `$ArrayElementAt`
384
+ - String: `$Concat`, `$ToLower`, `$ToUpper`, `$Split`
385
+ - Date: `$DateAdd`, `$DateSubtract`, `$DateDifference`
386
+ - Aggregation: `$Sum`, `$Average`, `$Min`, `$Max`
631
387
 
632
- // pipeline
633
- [ { $match: { '$expr': { '$gte': [ '$age', 18 ] } } } ]
634
- ```
388
+ ### Helpers
635
389
 
636
- ### [Merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge/)(value)
637
- #### Helper: `MergeHelper(into, optional)`
638
- ```typescript
639
- builder.Merge(MergeHelper('newCollection')).build();
390
+ 20+ helper functions for common patterns. See [complete list in stages.md](./docs/api/stages.md#complete-helpers-reference).
640
391
 
641
- // pipeline
642
- [ { $merge: { into: 'newCollection' } } ]
643
- ```
392
+ **Common Helpers:**
393
+ - `Field(name, value)` - Universal field helper
394
+ - `ProjectOnlyHelper(...fields)` - Include specific fields
395
+ - `LookupEqualityHelper(...)` - Simple joins
396
+ - `BucketHelper(...)` - Categorize documents
397
+ - `SearchHelper(...)` - Full-text search
644
398
 
645
- ### [Out](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out/)(value)
646
- #### Helper: `OutHelper(collection, optional)`
647
- ```typescript
648
- builder.Out(OutHelper('users')).build();
399
+ ---
649
400
 
650
- // pipeline
651
- [ { $out: 'users' } ]
652
- ```
401
+ ## πŸŽ“ Quick Examples
653
402
 
654
- ### [PlanCacheStats](https://www.mongodb.com/docs/manual/reference/operator/aggregation/planCacheStats/)()
403
+ ### Example 1: Simple Query
655
404
  ```typescript
656
- builder.PlanCacheStats().build();
657
-
658
- // pipeline
659
- [ { $planCacheStats: {} } ]
660
- ```
405
+ const pipeline = new PipelineBuilder('active-users')
406
+ .Match($Expression($Equal('$status', 'active')))
407
+ .Project(ProjectOnlyHelper('name', 'email'))
408
+ .Sort({ createdAt: -1 })
409
+ .Limit(10)
410
+ .build();
661
411
 
662
- ### [Project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project/)(...values)
663
- #### Helper: `ProjectHelper(field, value)`
664
- ```typescript
665
- builder.Project(
666
- ProjectHelper('age', '$user.age'),
667
- ProjectHelper(
668
- 'nickname',
669
- {
670
- $cond: {
671
- if: { $eq: [ '', '$user.nickname' ] },
672
- then: '$$REMOVE',
673
- else: '$user.nickname',
674
- },
675
- },
676
- ),
677
- ).build();
678
-
679
- // pipeline
680
- [
681
- {
682
- $project: {
683
- age: '$user.age',
684
- nickname: {
685
- $cond: {
686
- if: { $eq: [ '', '$user.nickname' ] },
687
- then: '$$REMOVE',
688
- else: '$user.nickname'
689
- }
690
- }
691
- }
692
- }
693
- ]
412
+ const result = await GetResult<User>(User, pipeline);
694
413
  ```
695
- #### Helper: `ProjectIgnoreHelper(...fields)`
696
- ```typescript
697
- builder.Project(ProjectIgnoreHelper('password', 'refreshToken')).build();
698
414
 
699
- // pipeline
700
- [ { $project: { password: 0, refreshToken: 0 } } ]
701
- ```
702
- #### Helper: `ProjectOnlyHelper(...fields)`
415
+ ### Example 2: With Pagination
703
416
  ```typescript
704
- builder.Project(ProjectOnlyHelper('password', 'refreshToken')).build();
417
+ const pipeline = new PipelineBuilder('paginated')
418
+ .Match($Expression($GreaterThan('$price', 100)))
419
+ .Sort({ price: -1 })
420
+ .Paging(20, 1)
421
+ .build();
705
422
 
706
- // pipeline
707
- [ { $project: { _id: 0, password: 1, refreshToken: 1 } } ]
423
+ const result = await GetPagingResult<Product>(Product, pipeline);
424
+ console.log(`Page 1 of ${result.GetTotalPageNumber()}`);
708
425
  ```
709
426
 
710
- ### [Redact](https://www.mongodb.com/docs/manual/reference/operator/aggregation/redact/)(value)
427
+ ### Example 3: With Joins
711
428
  ```typescript
712
- builder.Redact(
713
- $Condition(
714
- $GreaterThan($Size($SetIntersection('$tags', ['STLW', 'G'])), 0),
715
- '$$DESCEND',
716
- '$$PRUNE'
429
+ const pipeline = new PipelineBuilder('users-with-orders')
430
+ .Lookup(LookupEqualityHelper('orders', 'orders', '_id', 'userId'))
431
+ .AddFields(
432
+ Field('orderCount', $Size('$orders')),
433
+ Field('lastOrder', $ArrayElementAt('$orders', -1))
717
434
  )
718
- ).build();
719
-
720
- // pipeline
721
- [
722
- {
723
- $redact: {
724
- '$cond': [
725
- { '$gt': [ { '$size': { '$setIntersection': [ '$tags', [ 'STLW', 'G' ] ] } }, 0 ] },
726
- '$$DESCEND',
727
- '$$PRUNE'
728
- ]
729
- }
730
- }
731
- ]
435
+ .Match($Expression($GreaterThan('$orderCount', 0)))
436
+ .build();
732
437
  ```
733
438
 
734
- ### [ReplaceRoot](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replaceRoot/)(value)
439
+ ### Example 4: Complex Aggregation
735
440
  ```typescript
736
- builder.ReplaceRoot({
737
- newRoot: { full_name: { $concat : [ "$first_name", " ", "$last_name" ] } }
738
- }).build();
739
-
740
- // pipeline
741
- [
742
- {
743
- $replaceRoot: {
744
- newRoot: {
745
- full_name: { '$concat': [ '$first_name', ' ', '$last_name' ] }
746
- }
747
- }
748
- }
749
- ]
750
- ```
751
-
752
- ### [ReplaceWith](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replaceWith/)(value)
753
- ```typescript
754
- builder.ReplaceWith('$name').build();
755
-
756
- // pipeline
757
- [ { $replaceWith: '$name' } ]
441
+ const pipeline = new PipelineBuilder('sales-by-category')
442
+ .Match($Expression($Equal('$year', 2024)))
443
+ .Group({
444
+ _id: '$category',
445
+ totalSales: $Sum('$amount'),
446
+ averagePrice: $Average('$price'),
447
+ count: $Sum(1)
448
+ })
449
+ .Sort({ totalSales: -1 })
450
+ .Limit(10)
451
+ .build();
758
452
  ```
759
453
 
760
- ### [Sample](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sample/)(value)
761
- #### Helper: `SampleHelper(size)`
762
- ```typescript
763
- builder.Sample(SampleHelper(6)).build();
764
-
765
- // pipeline
766
- [ { $sample: { size: 6 } } ]
767
- ```
454
+ ---
768
455
 
769
- ### [Search](https://www.mongodb.com/docs/manual/reference/operator/aggregation/search/)(value)
770
- #### Helper: `SearchHelper(operator | collector, optional)`
771
- ```typescript
772
- builder.Search(
773
- SearchHelper({
774
- near: { path: 'released', origin: date, pivot: 7776000000 },
775
- }),
776
- ).build();
777
-
778
- // pipeline
779
- [
780
- {
781
- $search: {
782
- near: { path: 'released', origin: date, pivot: 7776000000 },
783
- },
784
- }
785
- ]
786
- ```
456
+ ## ❓ FAQ
787
457
 
788
- ### [SearchMeta](https://www.mongodb.com/docs/manual/reference/operator/aggregation/searchMeta/)(value)
789
- #### Helper: `SearchMetaHelper(collector, optional)`
790
- ```typescript
791
- builder.SearchMeta(
792
- SearchMetaHelper({
793
- facet: {
794
- operator: {
795
- near: { path: 'released', origin: date, pivot: 7776000000 },
796
- },
797
- facets: {
798
- test: { type: 'number', path: 'released', boundaries: [0, 100] },
799
- },
800
- },
801
- })
802
- ).build();
458
+ <details>
459
+ <summary><strong>When should I use GetResult vs GetPagingResult?</strong></summary>
803
460
 
804
- // pipeline
805
- [
806
- {
807
- $searchMeta: {
808
- facet: {
809
- operator: {
810
- near: { path: 'released', origin: date, pivot: 7776000000 },
811
- },
812
- facets: {
813
- test: { type: 'number', path: 'released', boundaries: [0, 100] },
814
- },
815
- },
816
- }
817
- }
818
- ]
819
- ```
461
+ - Use `GetResult` for queries **without** the `Paging` stage
462
+ - Use `GetPagingResult` **exclusively** when using the `Paging` stage
820
463
 
821
- ### [Set](https://www.mongodb.com/docs/manual/reference/operator/aggregation/set/)(...values)
822
- #### Helper: `Field(name, value)`
823
- ```typescript
824
- builder.Set(Field('first', true), Field('second', 2)).build();
464
+ The `Paging` stage wraps your pipeline in `$facet` for efficient pagination.
465
+ </details>
825
466
 
826
- // pipeline
827
- [ { $set: { first: true, second: 2 } } ]
828
- ```
467
+ <details>
468
+ <summary><strong>Can I use raw MongoDB syntax?</strong></summary>
829
469
 
830
- ### [SetWindowFields](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setWindowFields/)(value)
470
+ Yes! Use the `Insert` stage:
831
471
  ```typescript
832
- builder.SetWindowFields({
833
- partitionBy: "$state",
834
- sortBy: { orderDate: 1 },
835
- output: {
836
- cumulativeQuantityForState: {
837
- $sum: "$quantity",
838
- window: { documents: [ "unbounded", "current" ] }
839
- }
840
- }
841
- }).build();
842
-
843
- // pipeline
844
- [
845
- {
846
- $setWindowFields: {
847
- partitionBy: '$state',
848
- sortBy: { orderDate: 1 },
849
- output: {
850
- cumulativeQuantityForState: {
851
- '$sum': '$quantity',
852
- window: { documents: [ 'unbounded', 'current' ] }
853
- }
854
- }
855
- }
856
- }
857
- ]
472
+ builder.Insert({ $myCustomStage: { field: 'value' } })
858
473
  ```
474
+ Useful for new MongoDB stages or custom implementations.
475
+ </details>
859
476
 
860
- ### [ShardedDataDistribution](https://www.mongodb.com/docs/manual/reference/operator/aggregation/shardedDataDistribution/)(value)
861
- ```typescript
862
- builder.ShardedDataDistribution({}).build();
477
+ <details>
478
+ <summary><strong>Does it work with Mongoose?</strong></summary>
863
479
 
864
- // pipeline
865
- [ { $shardedDataDistribution: {} } ]
866
- ```
480
+ Yes! Works with:
481
+ - **MongoDB Native Driver:** `db.collection.aggregate()`
482
+ - **Mongoose:** `Model.aggregate()`
483
+ - **MongoDB Database Commands:** `db.aggregate()`
484
+ </details>
867
485
 
868
- ### [Skip](https://www.mongodb.com/docs/manual/reference/operator/aggregation/skip/)(value)
869
- ```typescript
870
- builder.Skip(100).build();
486
+ <details>
487
+ <summary><strong>Are all MongoDB stages supported?</strong></summary>
871
488
 
872
- // pipeline
873
- [ { $skip: 100 } ]
874
- ```
489
+ Yes! All stages through MongoDB 7.0+ including `$densify`, `$fill`, `$setWindowFields`, `$searchMeta`, and more.
490
+ </details>
875
491
 
876
- ### [Sort](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort/)(...values)
877
- #### Helper: `Field(name, value)`
878
- ```typescript
879
- builder.Sort(
880
- Field('first', -1),
881
- Field('second', 1),
882
- Field('third', { $meta: "textScore" }),
883
- ).build();
884
-
885
- // pipeline
886
- [
887
- {
888
- $sort: { first: -1, second: 1, third: { '$meta': 'textScore' } }
889
- }
890
- ]
891
- ```
492
+ <details>
493
+ <summary><strong>How do I handle TypeScript types?</strong></summary>
892
494
 
893
- ### [SortByCount](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sortByCount/)(value)
495
+ Use generics:
894
496
  ```typescript
895
- builder.SortByCount('$employee').build();
896
- // pipeline
897
-
898
- [ { $sortByCount: '$employee' } ]
497
+ interface User { name: string; email: string; }
498
+ const result = await GetResult<User>(User, pipeline);
499
+ const users: User[] = result.GetDocs(); // Fully typed!
899
500
  ```
501
+ </details>
900
502
 
901
- ### [UnionWith](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unionWith/)(value)
902
- #### Helper: `UnionWithHelper(collection, pipeline)`
903
- ```typescript
904
- builder.UnionWith(
905
- UnionWithHelper('cars'),
906
- ).build();
503
+ <details>
504
+ <summary><strong>Can I chain multiple lookups?</strong></summary>
907
505
 
908
- // pipeline
909
- [
910
- {
911
- $unionWith: { coll: 'cars' }
912
- }
913
- ]
914
- ```
506
+ Yes! Chain as many as needed:
915
507
  ```typescript
916
- builder.UnionWith(
917
- UnionWithHelper(
918
- undefined,
919
- [{ $document: [{ ref: 1 }, { ref: 2 }, { ref: 3 }], }]),
920
- ).build();
921
-
922
- // pipeline
923
- [
924
- {
925
- $unionWith: { pipeline: [ { '$document': [ { ref: 1 }, { ref: 2 }, { ref: 3 } ] } ] }
926
- }
927
- ]
508
+ builder
509
+ .Lookup(LookupEqualityHelper('profiles', 'profile', '_id', 'userId'))
510
+ .Lookup(LookupEqualityHelper('orders', 'orders', '_id', 'userId'))
511
+ .Lookup(LookupEqualityHelper('subscriptions', 'sub', '_id', 'userId'))
928
512
  ```
929
- ```typescript
930
- builder.UnionWith(
931
- UnionWithHelper('cars', [{ $match: { color: 'red' } }]),
932
- ).build();
513
+ See [Lookup Examples](./docs/examples/lookups.md).
514
+ </details>
933
515
 
934
- // pipeline
935
- [
936
- {
937
- $unionWith: { coll: 'cars', pipeline: [ { '$match': { color: 'red' } } ] }
938
- }
939
- ]
940
- ```
516
+ ---
941
517
 
942
- ### [Unset](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset/)(...values)
943
- ```typescript
944
- builder.Unset('users', 'roles').build();
518
+ ## πŸ“ˆ Performance Tips
945
519
 
946
- // pipeline
947
- [ { $unset: [ 'users', 'roles' ] } ]
948
- ```
520
+ 1. **Index your fields** - Create indexes on `$match` and `$sort` fields
521
+ 2. **Match early** - Apply `$match` as early as possible
522
+ 3. **Project early** - Remove unnecessary fields to reduce memory
523
+ 4. **Limit lookups** - Use pipeline syntax to limit joined documents
524
+ 5. **Use covered queries** - Query only indexed fields when possible
949
525
 
950
- ### [Unwind](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unwind/)(value)
951
- ```typescript
952
- builder.Unwind({ path: '$sizes', preserveNullAndEmptyArrays: true }).build();
526
+ > πŸ“– **Learn More:** [Pagination Examples](./docs/examples/pagination.md#performance-tips)
953
527
 
954
- // pipeline
955
- [ { $unwind: { path: '$sizes', preserveNullAndEmptyArrays: true } } ]
956
- ```
528
+ ---
957
529
 
958
- ___
530
+ ## πŸ†˜ Support
959
531
 
532
+ ### Getting Help
960
533
 
961
- # [MONGODB OPERATORS](https://docs.mongodb.com/manual/reference/operator/aggregation/)
534
+ - πŸ“– [Documentation](./docs/getting-started.md)
535
+ - πŸ› [Issue Tracker](https://github.com/MikeDev75015/mongodb-pipeline-builder/issues)
536
+ - πŸ’¬ [MongoDB Docs](https://docs.mongodb.com/manual/aggregation/)
962
537
 
963
- #### [$Absolute](https://www.mongodb.com/docs/manual/reference/operator/aggregation/abs/)
964
- ```typescript
965
- $Absolute(-5)
538
+ ### Reporting Issues
966
539
 
967
- // operator
968
- { $abs: -5 }
969
- ```
970
- #### [$Accumulator](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator/)
971
- ```typescript
972
- $Accumulator(
973
- () => ({ count: 0, sum: 0 }),
974
- (state: { count: number; sum: number; }, numCopies: number) => ({
975
- count: state.count + 1,
976
- sum: state.sum + numCopies,
977
- }),
978
- ['$copies'],
979
- (state1: { count: number; sum: number; }, state2: { count: number; sum: number; }) => ({
980
- count: state1.count + state2.count,
981
- sum: state1.sum + state2.sum,
982
- }),
983
- { finalize: (state: { sum: number; count: number; }) => (state.sum / state.count) },
984
- )
985
-
986
- // operator
987
- {
988
- '$accumulator': {
989
- init: [ () => ({ count: 0, sum: 0 }) ],
990
- accumulate: [
991
- (state: { count: number; sum: number; }, numCopies: number) => ({
992
- count: state.count + 1,
993
- sum: state.sum + numCopies,
994
- })
995
- ],
996
- accumulateArgs: [ '$copies' ],
997
- merge: [
998
- (state1: { count: number; sum: number; }, state2: { count: number; sum: number; }) => ({
999
- count: state1.count + state2.count,
1000
- sum: state1.sum + state2.sum,
1001
- })
1002
- ],
1003
- finalize: [ (state: { sum: number; count: number; }) => (state.sum / state.count) ],
1004
- lang: 'js'
1005
- }
1006
- }
1007
- ```
1008
- #### [$ArcCosine](https://www.mongodb.com/docs/manual/reference/operator/aggregation/acos/)
1009
- ```typescript
1010
- $ArcCosine({ $divide : [ '$side_b', '$hypotenuse' ] })
540
+ Include:
541
+ - Package version
542
+ - Node.js and MongoDB versions
543
+ - Code snippet
544
+ - Expected vs actual behavior
1011
545
 
1012
- // operator
1013
- { '$acos': { '$divide': [ '$side_b', '$hypotenuse' ] } }
1014
- ```
1015
- #### [$ArcCosineHyperbolic](https://www.mongodb.com/docs/manual/reference/operator/aggregation/acosh/)
1016
- ```typescript
1017
- $ArcCosineHyperbolic(3)
546
+ ---
1018
547
 
1019
- // operator
1020
- { '$acosh': 3 }
1021
- ```
1022
- #### [$Add](https://www.mongodb.com/docs/manual/reference/operator/aggregation/add/)
1023
- ```typescript
1024
- $Add('$price', 10)
1025
548
 
1026
- // operator
1027
- { '$add': [ '$price', 10 ] }
1028
- ```
1029
- #### [$AddToSet](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addToSet/)
1030
- ```typescript
1031
- $AddToSet('$item')
549
+ ## πŸ“œ Changelog
1032
550
 
1033
- // operator
1034
- { '$addToSet': '$item' }
1035
- ```
1036
- #### [$AllElementsTrue](https://www.mongodb.com/docs/manual/reference/operator/aggregation/allElementsTrue/)
1037
- ```typescript
1038
- $AllElementsTrue([ true, 1, "someString" ])
1039
-
1040
- // operator
1041
- { '$allElementsTrue': [ [ true, 1, 'someString' ] ] }
1042
- ```
1043
- #### [$And](https://www.mongodb.com/docs/manual/reference/operator/aggregation/and/)
1044
- ```typescript
1045
- $And(1, 'green')
1046
-
1047
- // operator
1048
- { '$and': [ 1, 'green' ] }
1049
- ```
1050
- #### [$AnyElementTrue](https://www.mongodb.com/docs/manual/reference/operator/aggregation/anyElementTrue/)
1051
- ```typescript
1052
- $AnyElementTrue([ true, false ])
1053
-
1054
- // operator
1055
- { '$anyElementTrue': [ [ true, false ] ] }
1056
- ```
1057
- #### [$ArrayElementAt](https://www.mongodb.com/docs/manual/reference/operator/aggregation/arrayElemAt/)
1058
- ```typescript
1059
- $ArrayElementAt([ 1, 2, 3 ], 0)
1060
-
1061
- // operator
1062
- { '$arrayElemAt': [ [ 1, 2, 3 ], 0 ] }
1063
- ```
1064
- #### [$ArrayToObject](https://www.mongodb.com/docs/manual/reference/operator/aggregation/arrayToObject/)
1065
- ```typescript
1066
- $ArrayToObject([ { "k": "item", "v": "abc123" }, { "k": "qty", "v": "$qty" } ])
1067
-
1068
- // operator
1069
- { '$arrayToObject': [ { k: 'item', v: 'abc123' }, { k: 'qty', v: '$qty' } ] }
1070
- ```
1071
- ```typescript
1072
- $ArrayToObject([ [ "item", "abc123" ], [ "qty", 25 ] ], true)
1073
-
1074
- // operator
1075
- { '$arrayToObject': { '$literal': [ [ 'item', 'abc123' ], [ 'qty', 25 ] ] } }
1076
- ```
1077
- #### [$ArcSine](https://www.mongodb.com/docs/manual/reference/operator/aggregation/asin/)
1078
- ```typescript
1079
- $ArcSine('$value')
1080
-
1081
- // operator
1082
- { '$asin': '$value' }
1083
- ```
1084
- #### [$ArcSineHyperbolic](https://www.mongodb.com/docs/manual/reference/operator/aggregation/asinh/)
1085
- ```typescript
1086
- $ArcSineHyperbolic('$value')
1087
-
1088
- // operator
1089
- { '$asinh': '$value' }
1090
- ```
1091
- #### [$ArcTangent](https://www.mongodb.com/docs/manual/reference/operator/aggregation/atan/)
1092
- ```typescript
1093
- $ArcTangent('$value')
1094
-
1095
- // operator
1096
- { '$atan': '$value' }
1097
- ```
1098
- #### [$ArcTangent2](https://www.mongodb.com/docs/manual/reference/operator/aggregation/atan2/)
1099
- ```typescript
1100
- $ArcTangent2('$side_b', '$side_a')
1101
-
1102
- // operator
1103
- { '$atan2': [ '$side_b', '$side_a' ] }
1104
- ```
1105
- #### [$ArcTangentHyperbolic](https://www.mongodb.com/docs/manual/reference/operator/aggregation/atanh/)
1106
- ```typescript
1107
- $ArcTangentHyperbolic('$value')
1108
-
1109
- // operator
1110
- { '$atanh': '$value' }
1111
- ```
1112
- #### [$Average](https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg/)
1113
- ```typescript
1114
- $Average('$value')
1115
-
1116
- // operator
1117
- { '$avg': '$value' }
1118
- ```
1119
- ```typescript
1120
- $Average('$value1', '$value2', '$value3')
1121
-
1122
- // operator
1123
- { '$avg': [ '$value1', '$value2', '$value3' ] }
1124
- ```
1125
- #### [$BinarySize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/binarySize/)
1126
- ```typescript
1127
- $BinarySize('Hello World!')
1128
-
1129
- // operator
1130
- { '$binarySize': 'Hello World!' }
1131
- ```
1132
- #### [$BitwiseAnd](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bitAnd/#mongodb-expression-exp.-bitAnd)
1133
- ```typescript
1134
- $BitwiseAnd('$array')
1135
-
1136
- // operator
1137
- { '$bitAnd': '$array' }
1138
- ```
1139
- ```typescript
1140
- $BitwiseAnd(0, 127, 5)
1141
-
1142
- // operator
1143
- { '$bitAnd': [ 0, 127, 5 ] }
1144
- ```
1145
- #### [$BitwiseNot](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bitNot/#mongodb-expression-exp.-bitNot)
1146
- ```typescript
1147
- $BitwiseNot('$long')
1148
-
1149
- // operator
1150
- { '$bitNot': '$long' }
1151
- ```
1152
- #### [$BitwiseOr](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bitOr/#mongodb-expression-exp.-bitOr)
1153
- ```typescript
1154
- $BitwiseOr('$array')
1155
-
1156
- // operator
1157
- { '$bitOr': '$array' }
1158
- ```
1159
- ```typescript
1160
- $BitwiseOr(0, 127, 5)
1161
-
1162
- // operator
1163
- { '$bitOr': [ 0, 127, 5 ] }
1164
- ```
1165
- #### [$BitwiseXor](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bitXor/#mongodb-expression-exp.-bitXor)
1166
- ```typescript
1167
- $BitwiseXor('$array')
1168
-
1169
- // operator
1170
- { '$bitXor': '$array' }
1171
- ```
1172
- ```typescript
1173
- $BitwiseXor(0, 127, 5)
1174
-
1175
- // operator
1176
- { '$bitXor': [ 0, 127, 5 ] }
1177
- ```
1178
- #### [$Bottom](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bottom/#mongodb-group-grp.-bottom)
1179
- ```typescript
1180
- $Bottom(['field1', 'field2'], { field2: -1 })
1181
-
1182
- // operator
1183
- { '$bottom': { output: [ 'field1', 'field2' ], sortBy: { field2: -1 } } }
1184
- ```
1185
- #### [$BottomN](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bottomN/#mongodb-group-grp.-bottomN)
1186
- ```typescript
1187
- $BottomN('field', { field: 1 }, 3)
1188
-
1189
- // operator
1190
- { '$bottomN': { output: 'field', sortBy: { field: 1 }, n: 3 } }
1191
- ```
1192
- #### [$BsonSize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bsonSize/)
1193
- ```typescript
1194
- $BsonSize('$$ROOT')
1195
-
1196
- // operator
1197
- { '$bsonSize': '$$ROOT' }
1198
- ```
1199
- #### [$Ceil](https://www.mongodb.com/docs/manual/reference/operator/aggregation/ceil/)
1200
- ```typescript
1201
- $Ceil('$value')
1202
-
1203
- // operator
1204
- { '$ceil': '$value' }
1205
- ```
1206
- #### [$Compare](https://www.mongodb.com/docs/manual/reference/operator/aggregation/cmp/)
1207
- ```typescript
1208
- $Compare('$age', 25)
1209
-
1210
- // operator
1211
- { '$cmp': [ '$age', 25 ] }
1212
- ```
1213
- #### [$Concat](https://www.mongodb.com/docs/manual/reference/operator/aggregation/concat/)
1214
- ```typescript
1215
- $Concat('$first', ' - ', '$second')
1216
-
1217
- // operator
1218
- { '$concat': [ '$first', ' - ', '$second' ] }
1219
- ```
1220
- #### [$ConcatArrays](https://www.mongodb.com/docs/manual/reference/operator/aggregation/concatArrays/)
1221
- ```typescript
1222
- $ConcatArrays('$array', [1, 2, 3])
1223
-
1224
- // operator
1225
- { '$concatArrays': [ '$array', [ 1, 2, 3 ] ] }
1226
- ```
1227
- #### [$Condition](https://www.mongodb.com/docs/manual/reference/operator/aggregation/cond/)
1228
- ```typescript
1229
- $Condition({ $gte: [ '$quantity', 250 ] }, 'true', 'false')
1230
-
1231
- // operator
1232
- { '$cond': [ { '$gte': [ '$quantity', 250 ] }, 'true', 'false' ] }
1233
- ```
1234
- #### [$Convert](https://www.mongodb.com/docs/manual/reference/operator/aggregation/convert/)
1235
- ```typescript
1236
- $Convert(100, 'bool')
1237
-
1238
- // operator
1239
- { '$convert': { input: 100, to: 'bool' } }
1240
- ```
1241
- #### [$Cosine](https://www.mongodb.com/docs/manual/reference/operator/aggregation/cos/)
1242
- ```typescript
1243
- $Cosine('$angle')
1244
-
1245
- // operator
1246
- { '$cos': '$angle' }
1247
- ```
1248
- #### [$CosineHyperbolic](https://www.mongodb.com/docs/manual/reference/operator/aggregation/cosh/)
1249
- ```typescript
1250
- $CosineHyperbolic({ $degreesToRadians : "$angle" })
1251
-
1252
- // operator
1253
- { '$cosh': { '$degreesToRadians': '$angle' } }
1254
- ```
1255
- #### [$Count](https://www.mongodb.com/docs/manual/reference/operator/aggregation/count-accumulator/)
1256
- ```typescript
1257
- $Count()
1258
-
1259
- // operator
1260
- { '$count': {} }
1261
- ```
1262
- #### [$CovariancePopulation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/covariancePop/)
1263
- ```typescript
1264
- $CovariancePopulation('$numeric1', '$numeric2')
1265
-
1266
- // operator
1267
- { '$covariancePopulation': [ '$numeric1', '$numeric2' ] }
1268
- ```
1269
- #### [$CovarianceSample](https://www.mongodb.com/docs/manual/reference/operator/aggregation/covarianceSamp/)
1270
- ```typescript
1271
- $CovarianceSample('$numeric1', '$numeric2')
1272
-
1273
- // operator
1274
- { '$covarianceSample': [ '$numeric1', '$numeric2' ] }
1275
- ```
1276
- #### [$DateAdd](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateAdd/)
1277
- ```typescript
1278
- $DateAdd('$startDate', 'hour', 2)
1279
-
1280
- // operator
1281
- { '$dateAdd': { startDate: '$startDate', unit: 'hour', amount: 2 } }
1282
- ```
1283
- #### [$DateDifference](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateDiff/)
1284
- ```typescript
1285
- $DateDifference('$startDate', '$endDate', 'second')
1286
-
1287
- // operator
1288
- { '$dateDiff': { startDate: '$startDate', endDate: '$endDate', unit: 'second' } }
1289
- ```
1290
- #### [$DateFromParts](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateFromParts/)
1291
- ```typescript
1292
- $DateFromCalendarParts(2000, { month: 12, day: 31, hour: 12, minute: 25, second: 59, timezone: '+01:00' })
1293
-
1294
- // operator
1295
- {
1296
- '$dateFromParts': {
1297
- year: 2000,
1298
- month: 12,
1299
- day: 31,
1300
- hour: 12,
1301
- minute: 25,
1302
- second: 59,
1303
- timezone: '+01:00'
1304
- }
1305
- }
1306
- ```
1307
- ```typescript
1308
- $DateFromIsoWeekParts(2000, { isoWeek: 53, isoDayOfWeek: 7, millisecond: 500 })
1309
-
1310
- // operator
1311
- { '$dateFromParts': { isoWeekYear: 2000, isoWeek: 53, isoDayOfWeek: 7, millisecond: 500 } }
1312
- ```
1313
- #### [$DateFromString](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateFromString/)
1314
- ```typescript
1315
- $DateFromString('2017-02-08T12:10:40.787', { timezone: 'America/New_York' })
1316
-
1317
- // operator
1318
- {
1319
- '$dateFromString': {
1320
- dateString: '2017-02-08T12:10:40.787',
1321
- timezone: 'America/New_York'
1322
- }
1323
- }
1324
- ```
1325
- #### [$DateSubtract](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateSubtract/)
1326
- ```typescript
1327
- $DateSubtract(1697382106124, 'month', 1)
1328
-
1329
- // operator
1330
- { '$dateSubtract': { startDate: 1697382106124, unit: 'month', amount: 1 } }
1331
- ```
1332
- #### [$DateToParts](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateToParts/)
1333
- ```typescript
1334
- $DateToParts(1697382106124)
1335
-
1336
- // operator
1337
- { '$dateToParts': { date: 1697382106124 } }
1338
- ```
1339
- #### [$DateToString](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateToString/)
1340
- ```typescript
1341
- $DateToString(1697382106124)
1342
-
1343
- // operator
1344
- { '$dateToString': { date: 1697382106124 } }
1345
- ```
1346
- #### [$DateTrunc](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dateTrunc/)
1347
- ```typescript
1348
- $DateTrunc(1697382106124, 'month')
1349
-
1350
- // operator
1351
- { '$dateTrunc': { date: 1697382106124, unit: 'month' } }
1352
- ```
1353
- #### [$DayOfMonth](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dayOfMonth/)
1354
- ```typescript
1355
- $DayOfMonth('$date', 'Europe/Paris')
1356
-
1357
- // operator
1358
- { '$dayOfMonth': { date: '$date', timezone: 'Europe/Paris' } }
1359
- ```
1360
- #### [$DayOfWeek](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dayOfWeek/)
1361
- ```typescript
1362
- $DayOfWeek('$date', '+03:30')
1363
-
1364
- // operator
1365
- { '$dayOfWeek': { date: '$date', timezone: '+03:30' } }
1366
- ```
1367
- #### [$DayOfYear](https://www.mongodb.com/docs/manual/reference/operator/aggregation/dayOfYear/)
1368
- ```typescript
1369
- $DayOfYear('$date')
1370
-
1371
- // operator
1372
- { '$dayOfYear': { date: '$date' } }
1373
- ```
1374
- #### [$DegreesToRadians](https://www.mongodb.com/docs/manual/reference/operator/aggregation/degreesToRadians/)
1375
- ```typescript
1376
- $DegreesToRadians('$angle_a')
1377
-
1378
- // operator
1379
- { '$degreesToRadians': '$angle_a' }
1380
- ```
1381
- #### $DenseRank
1382
- ```typescript
1383
-
1384
-
1385
- // operator
1386
-
1387
- ```
1388
- #### $Derivative
1389
- ```typescript
1390
-
1391
-
1392
- // operator
1393
-
1394
- ```
1395
- #### $Divide
1396
- ```typescript
1397
-
1398
-
1399
- // operator
1400
-
1401
- ```
1402
- #### $DocumentNumber
1403
- ```typescript
1404
-
1405
-
1406
- // operator
1407
-
1408
- ```
1409
- #### $Equal
1410
- ```typescript
1411
-
1412
-
1413
- // operator
1414
-
1415
- ```
1416
- #### $Exponent
1417
- ```typescript
1418
-
1419
-
1420
- // operator
1421
-
1422
- ```
1423
- #### $ExponentialMovingAverage
1424
- ```typescript
1425
-
1426
-
1427
- // operator
1428
-
1429
- ```
1430
- #### $Filter
1431
- ```typescript
1432
-
1433
-
1434
- // operator
1435
-
1436
- ```
1437
- #### $First
1438
- ```typescript
1439
-
1440
-
1441
- // operator
1442
-
1443
- ```
1444
- #### $FirstN
1445
- ```typescript
1446
-
1447
-
1448
- // operator
1449
-
1450
- ```
1451
- ```typescript
1452
-
1453
-
1454
- // operator
1455
-
1456
- ```
1457
- #### $Floor
1458
- ```typescript
1459
-
1460
-
1461
- // operator
1462
-
1463
- ```
1464
- #### $Function
1465
- ```typescript
1466
-
1467
-
1468
- // operator
1469
-
1470
- ```
1471
- #### $GetField
1472
- ```typescript
1473
-
1474
-
1475
- // operator
1476
-
1477
- ```
1478
- #### $GreaterThan
1479
- ```typescript
1480
-
1481
-
1482
- // operator
1483
-
1484
- ```
1485
- #### $GreaterThanEqual
1486
- ```typescript
1487
-
1488
-
1489
- // operator
1490
-
1491
- ```
1492
- #### $Hour
1493
- ```typescript
1494
-
1495
-
1496
- // operator
1497
-
1498
- ```
1499
- #### $IfNull
1500
- ```typescript
1501
-
1502
-
1503
- // operator
1504
-
1505
- ```
1506
- #### $In
1507
- ```typescript
1508
-
1509
-
1510
- // operator
1511
-
1512
- ```
1513
- #### $IndexOfArray
1514
- ```typescript
1515
-
1516
-
1517
- // operator
1518
-
1519
- ```
1520
- #### $IndexOfBytes
1521
- ```typescript
1522
-
1523
-
1524
- // operator
1525
-
1526
- ```
1527
- #### $IndexOfCodePoint
1528
- ```typescript
1529
-
1530
-
1531
- // operator
1532
-
1533
- ```
1534
- #### $Integral
1535
- ```typescript
1536
-
1537
-
1538
- // operator
1539
-
1540
- ```
1541
- #### $IsArray
1542
- ```typescript
1543
-
1544
-
1545
- // operator
1546
-
1547
- ```
1548
- #### $IsNumber
1549
- ```typescript
1550
-
1551
-
1552
- // operator
1553
-
1554
- ```
1555
- #### $IsoDayOfWeek
1556
- ```typescript
1557
-
1558
-
1559
- // operator
1560
-
1561
- ```
1562
- #### $IsoWeek
1563
- ```typescript
1564
-
1565
-
1566
- // operator
1567
-
1568
- ```
1569
- #### $IsoWeekYear
1570
- ```typescript
1571
-
1572
-
1573
- // operator
1574
-
1575
- ```
1576
- #### $Last
1577
- ```typescript
1578
-
1579
-
1580
- // operator
1581
-
1582
- ```
1583
- #### $LastN
1584
- ```typescript
1585
-
1586
-
1587
- // operator
1588
-
1589
- ```
1590
- ```typescript
1591
-
1592
-
1593
- // operator
1594
-
1595
- ```
1596
- #### $LessThan
1597
- ```typescript
1598
-
1599
-
1600
- // operator
1601
-
1602
- ```
1603
- #### $LessThanEqual
1604
- ```typescript
1605
-
1606
-
1607
- // operator
1608
-
1609
- ```
1610
- #### $Let
1611
- ```typescript
1612
-
1613
-
1614
- // operator
1615
-
1616
- ```
1617
- #### $Literal
1618
- ```typescript
1619
-
1620
-
1621
- // operator
1622
-
1623
- ```
1624
- #### $Log
1625
- ```typescript
1626
-
1627
-
1628
- // operator
1629
-
1630
- ```
1631
- #### $Log10
1632
- ```typescript
1633
-
1634
-
1635
- // operator
1636
-
1637
- ```
1638
- #### $Ltrim
1639
- ```typescript
1640
-
1641
-
1642
- // operator
1643
-
1644
- ```
1645
- #### $Map
1646
- ```typescript
1647
-
1648
-
1649
- // operator
1650
-
1651
- ```
1652
- #### $Max
1653
- ```typescript
1654
-
1655
-
1656
- // operator
1657
-
1658
- ```
1659
- #### $MergeObjects
1660
- ```typescript
1661
-
1662
-
1663
- // operator
1664
-
1665
- ```
1666
- #### $Meta
1667
- ```typescript
1668
-
1669
-
1670
- // operator
1671
-
1672
- ```
1673
- #### $Millisecond
1674
- ```typescript
1675
-
1676
-
1677
- // operator
1678
-
1679
- ```
1680
- #### $Min
1681
- ```typescript
1682
-
1683
-
1684
- // operator
1685
-
1686
- ```
1687
- #### $Minute
1688
- ```typescript
1689
-
1690
-
1691
- // operator
1692
-
1693
- ```
1694
- #### $Mod
1695
- ```typescript
1696
-
1697
-
1698
- // operator
1699
-
1700
- ```
1701
- #### $Month
1702
- ```typescript
1703
-
1704
-
1705
- // operator
1706
-
1707
- ```
1708
- #### $Multiply
1709
- ```typescript
1710
-
1711
-
1712
- // operator
1713
-
1714
- ```
1715
- #### $NaturalLog
1716
- ```typescript
1717
-
1718
-
1719
- // operator
1720
-
1721
- ```
1722
- #### $Not
1723
- ```typescript
1724
-
1725
-
1726
- // operator
1727
-
1728
- ```
1729
- #### $NotEqual
1730
- ```typescript
1731
-
1732
-
1733
- // operator
1734
-
1735
- ```
1736
- #### $ObjectToArray
1737
- ```typescript
1738
-
1739
-
1740
- // operator
1741
-
1742
- ```
1743
- #### $Or
1744
- ```typescript
1745
-
1746
-
1747
- // operator
1748
-
1749
- ```
1750
- #### $Pow
1751
- ```typescript
1752
-
1753
-
1754
- // operator
1755
-
1756
- ```
1757
- #### $Push
1758
- ```typescript
1759
-
1760
-
1761
- // operator
1762
-
1763
- ```
1764
- #### $RadiansToDegrees
1765
- ```typescript
1766
-
1767
-
1768
- // operator
1769
-
1770
- ```
1771
- #### $Rand
1772
- ```typescript
1773
-
1774
-
1775
- // operator
1776
-
1777
- ```
1778
- #### $Range
1779
- ```typescript
1780
-
1781
-
1782
- // operator
1783
-
1784
- ```
1785
- #### $Reduce
1786
- ```typescript
1787
-
1788
-
1789
- // operator
1790
-
1791
- ```
1792
- #### $RegexFind
1793
- ```typescript
1794
-
1795
-
1796
- // operator
1797
-
1798
- ```
1799
- #### $RegexFindAll
1800
- ```typescript
1801
-
1802
-
1803
- // operator
1804
-
1805
- ```
1806
- #### $RegexMatch
1807
- ```typescript
1808
-
1809
-
1810
- // operator
1811
-
1812
- ```
1813
- #### $ReplaceAll
1814
- ```typescript
1815
-
1816
-
1817
- // operator
1818
-
1819
- ```
1820
- #### $ReplaceOne
1821
- ```typescript
1822
-
1823
-
1824
- // operator
1825
-
1826
- ```
1827
- #### $ReverseArray
1828
- ```typescript
1829
-
1830
-
1831
- // operator
1832
-
1833
- ```
1834
- #### $Round
1835
- ```typescript
1836
-
1837
-
1838
- // operator
1839
-
1840
- ```
1841
- #### $Rtrim
1842
- ```typescript
1843
-
1844
-
1845
- // operator
1846
-
1847
- ```
1848
- #### $SampleRate
1849
- ```typescript
1850
-
1851
-
1852
- // operator
1853
-
1854
- ```
1855
- #### $Second
1856
- ```typescript
1857
-
1858
-
1859
- // operator
1860
-
1861
- ```
1862
- #### $SetDifference
1863
- ```typescript
1864
-
1865
-
1866
- // operator
1867
-
1868
- ```
1869
- #### $SetEquals
1870
- ```typescript
1871
-
1872
-
1873
- // operator
1874
-
1875
- ```
1876
- #### $SetIntersection
1877
- ```typescript
1878
-
1879
-
1880
- // operator
1881
-
1882
- ```
1883
- #### $SetIsSubset
1884
- ```typescript
1885
-
1886
-
1887
- // operator
1888
-
1889
- ```
1890
- #### $SetUnion
1891
- ```typescript
1892
-
1893
-
1894
- // operator
1895
-
1896
- ```
1897
- #### $Sin
1898
- ```typescript
1899
-
1900
-
1901
- // operator
1902
-
1903
- ```
1904
- #### $Sinh
1905
- ```typescript
1906
-
1907
-
1908
- // operator
1909
-
1910
- ```
1911
- #### $Size
1912
- ```typescript
1913
-
1914
-
1915
- // operator
1916
-
1917
- ```
1918
- #### $Slice
1919
- ```typescript
1920
-
1921
-
1922
- // operator
1923
-
1924
- ```
1925
- #### $Split
1926
- ```typescript
1927
-
1928
-
1929
- // operator
1930
-
1931
- ```
1932
- #### $Sqrt
1933
- ```typescript
1934
-
1935
-
1936
- // operator
1937
-
1938
- ```
1939
- #### $StdDevPop
1940
- ```typescript
1941
-
1942
-
1943
- // operator
1944
-
1945
- ```
1946
- #### $StdDevSamp
1947
- ```typescript
1948
-
1949
-
1950
- // operator
1951
-
1952
- ```
1953
- #### $StrCaseCmp
1954
- ```typescript
1955
-
1956
-
1957
- // operator
1958
-
1959
- ```
1960
- #### $StrLenBytes
1961
- ```typescript
1962
-
1963
-
1964
- // operator
1965
-
1966
- ```
1967
- #### $StrLenCP
1968
- ```typescript
1969
-
1970
-
1971
- // operator
1972
-
1973
- ```
1974
- #### $Substr
1975
- ```typescript
1976
-
1977
-
1978
- // operator
1979
-
1980
- ```
1981
- #### $SubstrBytes
1982
- ```typescript
1983
-
1984
-
1985
- // operator
1986
-
1987
- ```
1988
- #### $SubstrCP
1989
- ```typescript
1990
-
1991
-
1992
- // operator
1993
-
1994
- ```
1995
- #### $Subtract
1996
- ```typescript
1997
-
1998
-
1999
- // operator
2000
-
2001
- ```
2002
- #### $Sum
2003
- ```typescript
2004
-
2005
-
2006
- // operator
2007
-
2008
- ```
2009
- #### $Switch
2010
- ```typescript
2011
-
2012
-
2013
- // operator
2014
-
2015
- ```
2016
- #### $Tan
2017
- ```typescript
2018
-
2019
-
2020
- // operator
2021
-
2022
- ```
2023
- #### $Tanh
2024
- ```typescript
2025
-
2026
-
2027
- // operator
2028
-
2029
- ```
2030
- #### $ToBool
2031
- ```typescript
2032
-
2033
-
2034
- // operator
2035
-
2036
- ```
2037
- #### $ToDate
2038
- ```typescript
2039
-
2040
-
2041
- // operator
2042
-
2043
- ```
2044
- #### $ToDecimal
2045
- ```typescript
2046
-
2047
-
2048
- // operator
2049
-
2050
- ```
2051
- #### $ToDouble
2052
- ```typescript
2053
-
2054
-
2055
- // operator
2056
-
2057
- ```
2058
- #### $ToInt
2059
- ```typescript
2060
-
2061
-
2062
- // operator
2063
-
2064
- ```
2065
- #### $ToLong
2066
- ```typescript
2067
-
2068
-
2069
- // operator
2070
-
2071
- ```
2072
- #### $ToLower
2073
- ```typescript
2074
-
2075
-
2076
- // operator
2077
-
2078
- ```
2079
- #### $ToObjectId
2080
- ```typescript
2081
-
2082
-
2083
- // operator
2084
-
2085
- ```
2086
- #### $ToString
2087
- ```typescript
2088
-
2089
-
2090
- // operator
2091
-
2092
- ```
2093
- #### $ToUpper
2094
- ```typescript
2095
-
2096
-
2097
- // operator
2098
-
2099
- ```
2100
- #### $Trim
2101
- ```typescript
2102
-
2103
-
2104
- // operator
2105
-
2106
- ```
2107
- #### $Trunc
2108
- ```typescript
2109
-
2110
-
2111
- // operator
2112
-
2113
- ```
2114
- #### $Type
2115
- ```typescript
2116
-
2117
-
2118
- // operator
2119
-
2120
- ```
2121
- #### $Week
2122
- ```typescript
2123
-
2124
-
2125
- // operator
2126
-
2127
- ```
2128
- #### $Year
2129
- ```typescript
2130
-
2131
-
2132
- // operator
2133
-
2134
- ```
2135
- #### $Zip
2136
- ```typescript
2137
-
2138
-
2139
- // operator
2140
-
2141
- ```
551
+ See [CHANGELOG.md](./CHANGELOG.md) for version history.
2142
552
 
553
+ ---
2143
554
 
555
+ **Made with ❀️ by [Mickaël NODANCHE](https://cv-mikeonline.web.app)**