Skip to content

Commit d78fbbe

Browse files
committed
clarifying definitions and builders documentation.
1 parent 8b1130f commit d78fbbe

File tree

1 file changed

+61
-84
lines changed

1 file changed

+61
-84
lines changed

Docs/reference/content/reference/driver/definitions.md

Lines changed: 61 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -11,107 +11,75 @@ title = "Definitions and Builders"
1111

1212
## Definitions and Builders
1313

14-
The driver has introduced a number of types related to the specification of filters, updates, projections, sorts, etc... These types are used throughout the [API]({{< relref "reference\driver\crud\index.md" >}}). In addition, most of them have builders as well to aid in their creation.
14+
The driver has introduced a number of types related to the specification of filters, updates, projections, sorts, and index keys. These types are used throughout the [API]({{< relref "reference\driver\crud\index.md" >}}).
1515

16+
Most of the definitions also have builders to aid in their creation. Each builder has a generic type parameter `TDocument` which represents the type of document with which you are working. It will almost always match the generic `TDocument` parameter used in an [`IMongoCollection<TDocument>`]({{< apiref "T_MongoDB_Driver_IMongoCollection_1" >}}).
1617

17-
## Fields
1818

19-
[`FieldDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_FieldDefinition_1" >}}) and [`FieldDefinition<TDocument, TField>`]({{< apiref "T_MongoDB_Driver_FieldDefinition_2" >}}) define how to get a field name. They are implicitly convertible from a string, so that you can simply pass the field name you'd like.
19+
## Fields
2020

21-
For instance, with a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}), the following will be true:
21+
[`FieldDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_FieldDefinition_1" >}}) and [`FieldDefinition<TDocument, TField>`]({{< apiref "T_MongoDB_Driver_FieldDefinition_2" >}}) define how to get a field name. They are implicitly convertible from a string, so that you can simply pass the field name you'd like. For instance, to use the field named "fn" with a `TDocument` of [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}), do the following:
2222

2323
```csharp
24-
// method definition
25-
string GetFieldName<TDocument>(FieldDefinition<TDocument> field);
26-
27-
// invocation
28-
var fieldName = GetFieldName<BsonDocument>("fun");
29-
30-
fieldName.Should().Be("fun");
24+
FieldDefinition<BsonDocument> field = "fn";
3125
```
3226

33-
However, if you are working with a [mapped class]({{< relref "reference\bson\mapping\index.md" >}}), then 2 further options exist.
34-
35-
First, most locations that accept a [`FieldDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_FieldDefinition_1" >}}) or [`FieldDefinition<TDocument, TField>`]({{< apiref "T_MongoDB_Driver_FieldDefinition_2" >}}) will also have an overload (via extension method) that accepts a lambda expression. Given the following class definition marked with the [`BsonElementAttribute`]({{< apiref "T_MongoDB_Bson_Serialization_Attributes_BsonElementAttribute" >}}) instructing the use of a different field name:
27+
However, if you are working with a [mapped class]({{< relref "reference\bson\mapping\index.md" >}}), then we are able to translate a string that equals the property name. For instance, given the below `Person` class:
3628

3729
```csharp
3830
class Person
3931
{
4032
[BsonElement("fn")]
4133
public string FirstName { get; set; }
4234

43-
[BsonElement("fn")]
35+
[BsonElement("ln")]
4436
public string LastName { get; set; }
4537
}
4638
```
4739

48-
Then the following will be true.
40+
Since we know the type is `Person`, we can provide the property name, `FirstName`, from the class and "fn" will still be used.
4941

5042
```csharp
51-
// method definition
52-
string GetFieldName<TDocument>(Expression<Func<TDocument, object>> field);
53-
54-
// invocation
55-
var fieldName = GetFieldName<Person>(x => x.FirstName);
56-
57-
fieldName.Should().Be("fn");
43+
FieldDefinition<Person> field = "FirstName";
5844
```
59-
60-
In the same way, since we know the type of document, `Person` in this case, we can also translate fields names provided as a string.
45+
{{% note %}}We don't validate that the provided string exists as a mapped field, so it is still possible to provide a field that hasn't been mapped:{{% /note %}}
6146

6247
```csharp
63-
// method definition
64-
string GetFieldName<TDocument>(FieldDefinition<TDocument> field);
65-
66-
// invocation
67-
var fieldName = GetFieldName<Person>("FirstName");
68-
69-
fieldName.Should().Be("fn");
48+
FieldDefinition<Person> field = "fn";
7049
```
7150

72-
Finally, we don't validate that the provided string exists as a mapped field, so it is still possible to provide a field that hasn't been mapped:
73-
74-
```csharp
75-
// method definition
76-
string GetFieldName<TDocument>(FieldDefinition<TDocument> field);
77-
78-
// invocation
79-
var fieldName = GetFieldName<Person>("fn");
80-
81-
fieldName.Should().Be("fn");
82-
```
51+
And the output field name of this will be just "fn".
8352

8453

8554
## Filters
8655

87-
[`FilterDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_FilterDefinition_1" >}}) defines a filter. It is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}). Given the following method, all the following are valid:
56+
[`FilterDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_FilterDefinition_1" >}}) defines a filter. It is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}).
8857

8958
```csharp
90-
// method definition
91-
BsonDocument Filter(FilterDefinition<BsonDocument> filter);
59+
FilterDefinition<BsonDocument> filter = "{ x: 1 }";
9260

93-
// invocation
94-
var doc = Filter("{ x: 1 }");
95-
doc.ToJson().Should().Be("{ x: 1 }");
61+
// or
9662
97-
var doc = Filter(new BsonDocument("x", 1));
98-
doc.ToJson().Should().Be("{ x: 1 }");
63+
FilterDefinition<BsonDocument> filter = new BsonDocument("x", 1);
9964
```
10065

66+
Both of these will render the filter `{ x: 1 }`.
67+
68+
10169
### Filter Definition Builder
10270

10371
_See the [tests]({{< srcref "MongoDB.Driver.Tests/FilterDefinitionBuilderTests.cs" >}}) for examples._
10472

105-
The [`FilterDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_FilterDefinitionBuilder_1" >}}) provides a nice API for building up both simple and complex [MongoDB queries]({{< docsref "reference/operator/query/" >}}).
73+
The [`FilterDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_FilterDefinitionBuilder_1" >}}) provides a type-safe API for building up both simple and complex [MongoDB queries]({{< docsref "reference/operator/query/" >}}).
10674

107-
For example, to build up the filter `{ x: 10, y: { $lt: 20 } }`, the following calls are all comparable.
75+
For example, to build up the filter `{ x: 10, y: { $lt: 20 } }`, the following calls are all equivalent.
10876

10977
```csharp
11078
var builder = Builders<BsonDocument>.Filter;
11179
var filter = builder.Eq("x", 10) & builder.Lt("y", 20);
11280
```
11381

114-
{{% note %}}Note that the `&` operator is overloaded. Other overloaded operators include the `|` operator for "or" and the `!` operator for "not".{{% /note %}}
82+
{{% note %}}The `&` operator is overloaded. Other overloaded operators include the `|` operator for "or" and the `!` operator for "not".{{% /note %}}
11583

11684
Given the following class:
11785

@@ -126,27 +94,25 @@ class Widget
12694
}
12795
```
12896

129-
We can achieve the same result in the typed variant:
97+
You can achieve the same result in the typed variant:
13098

13199
```csharp
132100
var builder = Builders<Widget>.Filter;
133-
var filter = builder.Eq(x => x.X, 10) & builder.Lt(x => x.Y, 20);
101+
var filter = builder.Eq(widget => widget.X, 10) & builder.Lt(widget => widget.Y, 20);
102+
```
134103

135-
// or
104+
The benefits to this form is the compile-time safety inherent in using types. In addition, your IDE can provide refactoring support.
136105

106+
Alternatively, you can elect to use a string-based field name instead.
107+
108+
```csharp
137109
var filter = builder.Eq("X", 10) & builder.Lt("Y", 20);
138110

139111
// or
140112
141113
var filter = builder.Eq("x", 10) & builder.Lt("y", 20);
142114
```
143115

144-
Or via a lambda expression:
145-
146-
```csharp
147-
var filter = Builders<Widget>.Filter.Where(x => x.X == 10 && x.Y < 20);
148-
```
149-
150116
For more information on valid lambda expressions, see the [expressions documentation]({{< relref "reference\driver\expressions.md" >}}).
151117

152118
#### Array Operators
@@ -190,13 +156,26 @@ PipelineDefinition pipeline = new BsonDocument[]
190156

191157
## Projections
192158

193-
There are two forms of a projection definition, one where the type of the projection is known ([`ProjectionDefinition<TDocument, TProjection>`]({{< apiref "T_MongoDB_Driver_ProjectionDefinition_2" >}})) and one where the type of the projection is not yet known ([`ProjectionDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_ProjectionDefinition_1" >}})). The latter, while implicitly convertible to the first, is merely used as a building block. The [high-level APIs]({{< relref "reference\driver\crud\index.md" >}}) that take a projection will always take the former. This is because, when determining how to handle a projection client-side, it is not enough to know what fields and transformations will take place. It also requires that we know how to interpret the projected shape as a .NET type. Since the driver allows you to work with custom classes, it is imperative that any projection also include the "interpretation instructions" for projecting into a custom class.
159+
There are two forms of a projection definition: one where the type of the projection is known, [`ProjectionDefinition<TDocument, TProjection>`]({{< apiref "T_MongoDB_Driver_ProjectionDefinition_2" >}}), and one where the type of the projection is not yet known, [`ProjectionDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_ProjectionDefinition_1" >}}). The latter, while implicitly convertible to the first, is merely used as a building block. The [high-level APIs]({{< relref "reference\driver\crud\index.md" >}}) that take a projection will always take the former. This is because, when determining how to handle a projection client-side, it is not enough to know what fields and transformations will take place. It also requires that we know how to interpret the projected shape as a .NET type. Since the driver allows you to work with custom classes, it is imperative that any projection also include the "interpretation instructions" for projecting into a custom class.
160+
161+
Each projection definition is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}).
162+
163+
```csharp
164+
ProjectionDefinition<BsonDocument> projection = "{ x: 1 }";
165+
166+
// or
167+
168+
ProjectionDefinition<BsonDocument> projection = new BsonDocument("x", 1);
169+
```
170+
171+
Both of these will render the projection `{ x: 1 }`.
172+
194173

195174
### Projection Definition Builder
196175

197176
_See the [tests]({{< srcref "MongoDB.Driver.Tests/ProjectionDefinitionBuilderTests.cs" >}}) for examples._
198177

199-
The [`ProjectionDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_ProjectionDefinitionBuilder_1" >}}) exists to make it easier to build up projections in MongoDB's syntax. To render the projection `{ x: 1, y: 1, _id: 0 }`, the following should be done:
178+
The [`ProjectionDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_ProjectionDefinitionBuilder_1" >}}) exists to make it easier to build up projections in MongoDB's syntax. For the projection `{ x: 1, y: 1, _id: 0 }`:
200179

201180
```csharp
202181
var projection = Builders<BsonDocument>.Projection.Include("x").Include("y").Exclude("_id");
@@ -295,25 +274,23 @@ A projection is also used when performing grouping in the [Aggregation Framework
295274

296275
## Sorts
297276

298-
[`SortDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_SortDefinition_1" >}}) defines how to render a valid sort document. It is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}). Given the following method, all the following are valid:
277+
[`SortDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_SortDefinition_1" >}}) defines how to render a valid sort document. It is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}).
299278

300279
```csharp
301-
// method definition
302-
BsonDocument Sort(SortDefinition<BsonDocument> filter);
280+
SortDefinition<BsonDocument> sort = "{ x: 1 }";
303281

304-
// invocation
305-
var doc = Sort("{ x: 1 }");
306-
doc.ToJson().Should().Be("{x : 1 }");
282+
// or
307283
308-
var doc = Sort(new BsonDocument("x", 1));
309-
doc.ToJson().Should().Be("{ x: 1 }");
284+
SortDefinition<BsonDocument> sort = new BsonDocument("x", 1);
310285
```
311286

287+
Both of these will render the sort `{ x: 1 }`.
288+
312289
### Sort Definition Builder
313290

314291
_See the [tests]({{< srcref "MongoDB.Driver.Tests/SortDefinitionBuilderTests.cs" >}}) for examples._
315292

316-
The [`SortDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_SortDefinitionBuilder_1" >}}) provides a nice API for building up [MongoDB sort syntax]({{< docsref "reference/method/cursor.sort/" >}}).
293+
The [`SortDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_SortDefinitionBuilder_1" >}}) provides a type-safe API for building up [MongoDB sort syntax]({{< docsref "reference/method/cursor.sort/" >}}).
317294

318295
For example, to build up the sort `{ x: 1, y: -1 }`, do the following:
319296

@@ -353,25 +330,25 @@ var sort = builder.Ascending("x").Descending("y");
353330

354331
## Updates
355332

356-
[`UpdateDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_UpdateDefinition_1" >}}) defines how to render a valid update document. It is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}). Given the following method, all the following are valid:
333+
[`UpdateDefinition<TDocument>`]({{< apiref "T_MongoDB_Driver_UpdateDefinition_1" >}}) defines how to render a valid update document. It is implicity convertible from both a JSON string as well as a [`BsonDocument`]({{< apiref "T_MongoDB_Bson_BsonDocument" >}}).
357334

358335
```csharp
359-
// method definition
360-
BsonDocument Update(UpdateDefinition<BsonDocument> filter);
361-
362336
// invocation
363-
var doc = Update("{ $set: { x: 1 } }");
364-
doc.ToJson().Should().Be("{ $set: { x: 1 } }");
337+
UpdateDefinition<BsonDocument> update = "{ $set: { x: 1 } }";
338+
339+
// or
365340
366-
var doc = Sort(new BsonDocument("$set", new BsonDocument("x", 1)));
367-
doc.ToJson().Should().Be("{ $set: { x: 1 } }");
341+
UpdateDefinition<BsonDocument> update = new BsonDocument("$set", new BsonDocument("x", 1));
368342
```
369343

344+
Both of these will render the update `{ $set: { x: 1 } }`.
345+
346+
370347
### Update Definition Builder
371348

372349
_See the [tests]({{< srcref "MongoDB.Driver.Tests/UpdateDefinitionBuilderTests.cs" >}}) for examples._
373350

374-
The [`UpdateDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_UpdateDefinitionBuilder_1" >}}) provides a nice API for building the [MongoDB update specification]({{< docsref "reference/operator/update/" >}}).
351+
The [`UpdateDefinitionBuilder<TDocument>`]({{< apiref "T_MongoDB_Driver_UpdateDefinitionBuilder_1" >}}) provides a type-safe API for building the [MongoDB update specification]({{< docsref "reference/operator/update/" >}}).
375352

376353
For example, to build up the update `{ $set: { x: 1, y: 3 }, $inc: { z: 1 } }`, do the following:
377354

@@ -400,7 +377,7 @@ We can achieve the same result in a typed variant:
400377

401378
```csharp
402379
var builder = Builders<Widget>.Update;
403-
var update = builder.Set(x => x.X, 1).Set(x => x.Y, 3).Inc(x => x.Z, 1);
380+
var update = builder.Set(widget => widget.X, 1).Set(widget => widget.Y, 3).Inc(widget => widget.Z, 1);
404381

405382
// or
406383

0 commit comments

Comments
 (0)