Skip to content

Commit 9108cac

Browse files
committed
added aggregate documentation.
1 parent 33b3d58 commit 9108cac

File tree

1 file changed

+145
-0
lines changed
  • Docs/reference/content/reference/driver/crud

1 file changed

+145
-0
lines changed

Docs/reference/content/reference/driver/crud/reading.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,149 @@ When you only want to find one document, the `FirstAsync`, `FirstOrDefaultAsync`
102102
var result = await collection.Find(filter)
103103
.Skip(10)
104104
.FirstOrDefaultAsync();
105+
```
106+
107+
## Aggregation
108+
109+
MongoDB offers the [aggregation framework]({{< docsref "core/aggregation-pipeline/" >}}) which can be accessed via the [`Aggregate`]({{< apiref "M_MongoDB_Driver_IMongoCollectionExtensions_Aggregate__1" >}}) method. The result type is [`IAggregateFluent`]({{< apiref "T_MongoDB_Driver_IAggregateFluent_1" >}}) and provides access to build up and aggregation pipeline.
110+
111+
The first example from [MongoDB's documentation]({{< docsref "tutorial/aggregation-zip-code-data-set/#return-states-with-populations-above-10-million" >}}) is done in a type-safe manner below:
112+
113+
```csharp
114+
[BsonIgnoreExtraElements]
115+
class ZipEntry
116+
{
117+
[BsonId]
118+
public string Zip { get; set; }
119+
120+
[BsonElement("city")]
121+
public string City { get; set; }
122+
123+
[BsonElement("state")]
124+
public string State { get; set; }
125+
126+
[BsonElement("pop")]
127+
public int Population { get; set; }
128+
}
129+
130+
var pipeline = db.GetCollection<ZipEntry>.Aggregate()
131+
.Group(x => x.State, g => new { State = g.Key, TotalPopulation = g.Sum(x => x.Population) })
132+
.Match(x => x.TotalPopulation > 20000);
133+
```
134+
135+
This will result in the following aggregation pipeline getting sent to the server:
136+
137+
```json
138+
[{ group: { _id: '$state', TotalPopulation: { $sum : '$pop' } } },
139+
{ $match: { TotalPopulation: { $gt: 20000 } } }]
140+
```
141+
142+
{{% note %}}You can call `ToString` on the pipeline to see what would be sent to the server.{{% /note %}}
143+
144+
More samples are located in the [source]({{< srcref "MongoDB.Driver.Tests/Samples/AggregationSample.cs" >}}.
145+
146+
### Stage Operators
147+
148+
All the [stage operators]({{< docsref "reference/operator/aggregation/#aggregation-pipeline-operator-reference" >}}) are supported, however some of them must use the [`AppendStage`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_AppendStage__1" >}}) method due to lack of support for certain projections in the language.
149+
150+
{{% note class="important" %}}Unlike `Find`, the order that stages are defined in matters. `Skip(10).Limit(10)` is not the same as `Limit(10).Skip(10)`.{{% /note %}}
151+
152+
#### $project
153+
154+
A `$project` is rendered using the [`Project`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Project__1" >}}) method and its overloads. Unlike in `Find`, an aggregate projection is not executed client-side and must be fully translatable to the server's supported expressions. See [expressions]({{< relref "reference\driver\expressions.md#projections" >}}) for more detail about the expressions available inside a $project.
155+
156+
```csharp
157+
Project(x => new { Name = x.FirstName + " " + x.LastName });
158+
```
159+
```json
160+
{ $project: { Name: { $concat: ['$FirstName', ' ', '$LastName'] } } }
161+
```
162+
163+
{{% note %}}In an aggregation framework projection, a new type, either anonymous or named, must be used.{{% /note %}}
164+
165+
#### $match
166+
167+
A `$match` stage is rendered using the [`Match`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Match" >}}) method and its overloads. It follows the same requirements as that of `Find`.
168+
169+
```csharp
170+
Match(x => x.Age > 21);
171+
```
172+
```json
173+
{ $match: { Age: { $gt: 21 } } }
174+
```
175+
176+
#### $redact
177+
178+
There is no method defined for a `$redact` stage. However, it can be added using [`AppendStage`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_AppendStage__1" >}}).
179+
180+
#### $limit
181+
182+
A `$limit` stage is rendered using the [`Limit`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Limit" >}}) method.
183+
184+
```csharp
185+
Limit(20);
186+
```
187+
```json
188+
{ $limit: 20 }
189+
```
190+
191+
#### $skip
192+
193+
A `$skip` stage is rendered using the [`Skip`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Skip" >}}) method.
194+
195+
```csharp
196+
Skip(20);
197+
```
198+
```json
199+
{ $skip: 20 }
200+
```
201+
202+
#### $unwind
203+
204+
An `$unwind` stage is rendered using the [`Unwind`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Unwind__1" >}}) method and its overloads. Because $unwind is a type of projection, you must provide a return type, although not specifying one will use the overload that projects into a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}).
205+
206+
```csharp
207+
Unwind(x => x.ArrayFieldToUnwind);
208+
```
209+
```json
210+
{ $unwind: 'ArrayFieldToUnwind' }
211+
```
212+
213+
#### $group
214+
215+
A `$group` stage is rendered using the [`Group`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Group__1" >}}) method and its overloads. Because $unwind is a type of projection, you must provide a return type. The most useful of the overloads is where 2 lambda expressions are expressed, the first for the key and the second for the grouping. See [expressions]({{< relref "reference\driver\expressions.md#grouping" >}}) for more detail about the expressions available inside a $group.
216+
217+
```csharp
218+
Group(x => x.Name, g => new { Name = g.Key, AverageAge = g.Average(x = x.Age) });
219+
```
220+
```json
221+
{ $group: { _id: '$Name', AverageAge: { $avg: '$Age'} } }
222+
```
223+
224+
As in project, it is required that the result of the grouping be a new type, either anonymous or named. If the `Key` of the grouping is not used, an `_id` will still be inserted as this is required by the `$group` operator.
225+
226+
#### $sort
227+
228+
A `$sort` stage is rendered using the [`Sort`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Sort" >}}) method. However, `SortBy`, `SortByDescending`, `ThenBy`, and `ThenByDescending` are also present.
229+
230+
```csharp
231+
SortBy(x => x.LastName).ThenByDescending(x => x.Age);
232+
```
233+
```json
234+
{ $sort: { LastName: 1, Age: -1 } }
235+
```
236+
237+
#### $geoNear
238+
239+
There is no method defined for a `$geoNear` stage. However, it can be added using [`AppendStage`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_AppendStage__1" >}}).
240+
241+
#### $out
242+
243+
A `$out` stage is rendered using the [`Out`]({{< apiref "M_MongoDB_Driver_IAggregateFluent_1_Out" >}}) method.
244+
245+
```csharp
246+
Out("myNewCollection");
247+
```
248+
```json
249+
{ $out: 'myNewCollection' }
105250
```

0 commit comments

Comments
 (0)