|
| 1 | +.. _csharp-builders: |
| 2 | + |
| 3 | +======================== |
| 4 | +Operations with Builders |
| 5 | +======================== |
| 6 | + |
| 7 | +.. default-domain:: mongodb |
| 8 | + |
| 9 | +.. contents:: On this page |
| 10 | + :local: |
| 11 | + :backlinks: none |
| 12 | + :depth: 2 |
| 13 | + :class: singlecol |
| 14 | + |
| 15 | +Overview |
| 16 | +-------- |
| 17 | + |
| 18 | +In this guide, you can learn about the helper classes, or **builders**, that |
| 19 | +the {+driver-short+} provides to create types used in your operations. |
| 20 | +Using builders helps you identify errors at compile time and avoid them |
| 21 | +at runtime. This guide provides information on builder classes that you |
| 22 | +can use for the following tasks: |
| 23 | + |
| 24 | +- Creating a filter definition |
| 25 | +- Creating a projection |
| 26 | +- Defining a sort order |
| 27 | +- Defining an update operation |
| 28 | +- Selecting index keys |
| 29 | + |
| 30 | +.. tip:: MongoDB Analyzer |
| 31 | + |
| 32 | + The MongoDB Analyzer is a tool that helps you analyze your |
| 33 | + builders definitions and understand how your {+lang-framework+} code |
| 34 | + translates into the MongoDB Query API. For more information and |
| 35 | + installation instructions, see the `MongoDB Analyzer reference page <https://www.mongodb.com/docs/mongodb-analyzer/current/>`__. |
| 36 | + |
| 37 | +You should read this guide if you want to learn more about how to |
| 38 | +construct definitions and build up syntax using builders. |
| 39 | + |
| 40 | +Sample Class |
| 41 | +------------ |
| 42 | + |
| 43 | +The code examples in this guide demonstrate how you can use builders to |
| 44 | +create types to interact with documents in the sample collection ``plants.flowers``. |
| 45 | +Documents in this collection are modeled by the following ``Flower`` class: |
| 46 | + |
| 47 | +.. literalinclude:: /includes/fundamentals/code-examples/builders.cs |
| 48 | + :language: csharp |
| 49 | + :dedent: |
| 50 | + :start-after: start-model |
| 51 | + :end-before: end-model |
| 52 | + |
| 53 | +Each builder class takes a generic type parameter |
| 54 | +``TDocument`` which represents the type of document that you are working |
| 55 | +with. In this guide, the ``Flower`` class is the document type used in |
| 56 | +each builder class example. |
| 57 | + |
| 58 | +Construct a Filter |
| 59 | +------------------ |
| 60 | + |
| 61 | +The ``FilterDefinitionBuilder`` class provides a type-safe interface for |
| 62 | +building up queries. Suppose you want to query your collection for |
| 63 | +documents matching the following criteria: |
| 64 | + |
| 65 | +- ``Price`` field value less than 20 |
| 66 | +- ``Category`` field value is "Perennial" |
| 67 | + |
| 68 | +Use builders to create the filter definition with the typed variant: |
| 69 | + |
| 70 | +.. code-block:: csharp |
| 71 | + :copyable: true |
| 72 | + |
| 73 | + var builder = Builders<Flower>.Filter; |
| 74 | + var filter = builder.Lt(f => f.Price, 20) & builder.Eq(f => f.Category, "Perennial"); |
| 75 | + |
| 76 | +Using the typed variant form provides compile-time safety. Additionally, |
| 77 | +your IDE can provide refactoring support. |
| 78 | + |
| 79 | +Alternatively, you can use string-based field names to contruct the filter: |
| 80 | + |
| 81 | +.. code-block:: csharp |
| 82 | + :copyable: true |
| 83 | + |
| 84 | + var builder = Builders<Flower>.Filter; |
| 85 | + var filter = builder.Lt("Price", 20) & builder.Eq("Category", "Perennial"); |
| 86 | + |
| 87 | +Array Operators |
| 88 | +~~~~~~~~~~~~~~~ |
| 89 | + |
| 90 | +If your document has properties or fields that serialize to arrays, |
| 91 | +you can use the methods beginning with ``Any``, such as ``AnyEq()`` or |
| 92 | +``AnyLt()``, to compare the entire array against a single item. |
| 93 | + |
| 94 | +Use builders to check which documents in the collection have a |
| 95 | +``Season`` array that includes "winter": |
| 96 | + |
| 97 | +.. code-block:: csharp |
| 98 | + :copyable: true |
| 99 | + |
| 100 | + var builder = Builders<Flower>.Filter; |
| 101 | + var filter = builder.AnyEq(f => f.Season, "winter"); |
| 102 | + |
| 103 | +.. TODO for a complete list of expressions, see the Query page? |
| 104 | + |
| 105 | +Create a Projection |
| 106 | +------------------- |
| 107 | + |
| 108 | +The ``ProjectionDefinitionBuilder`` class provides a type-safe interface for |
| 109 | +defining a projection. Suppose you want to create a projection on the |
| 110 | +``Name`` and ``Price`` fields, but exclude the ``Id`` field. |
| 111 | + |
| 112 | +Use builders to create the projection definition with the typed variant: |
| 113 | + |
| 114 | +.. code-block:: csharp |
| 115 | + :copyable: true |
| 116 | + |
| 117 | + var builder = Builders<Flower>.Projection; |
| 118 | + var projection = builder.Include(f => f.Name).Include(f => f.Price).Exclude(f => f.Id); |
| 119 | + |
| 120 | +You can also use string-based field names to define the projection: |
| 121 | + |
| 122 | +.. code-block:: csharp |
| 123 | + :copyable: true |
| 124 | + |
| 125 | + var builder = Builders<Flower>.Projection; |
| 126 | + var projection = builder.Include("Name").Include("Price").Exclude("Id"); |
| 127 | + |
| 128 | +Finally, you can use the ``Expression()`` method to define the |
| 129 | +projection: |
| 130 | + |
| 131 | +.. code-block:: csharp |
| 132 | + :copyable: true |
| 133 | + |
| 134 | + var builder = Builders<Flower>.Projection; |
| 135 | + var projection = builder.Expression(f => new { Name = f.Name, Price = f.Price }); |
| 136 | + |
| 137 | +This definition has a return type of ``ProjectionDefinition<TDocument, |
| 138 | +TProjection>`` whereas the others return a |
| 139 | +``ProjectionDefinition<TDocument>``. |
| 140 | + |
| 141 | +Lambda Expressions |
| 142 | +~~~~~~~~~~~~~~~~~~ |
| 143 | + |
| 144 | +The driver supports using lambda expressions to render projections. When |
| 145 | +you define a ``Find()`` projection with the ``Expression()`` method to |
| 146 | +create a lambda expression, the driver inspects the expression |
| 147 | +to determine which fields are referenced and automatically constructs a |
| 148 | +server-side projection to return only those fields. |
| 149 | + |
| 150 | +You can also use lambda expressions to create new fields by performing |
| 151 | +operations on values in your documents. The following example shows how |
| 152 | +you can use a lambda expression to project a new ``Profit`` field |
| 153 | +using the ``Price`` and ``Stock`` fields: |
| 154 | + |
| 155 | +.. code-block:: csharp |
| 156 | + :copyable: true |
| 157 | + |
| 158 | + var builder = Builders<Flower>.Projection; |
| 159 | + var projection = builder.Expression(f => new { Profit = f.Price * f.Stock }); |
| 160 | + |
| 161 | +.. note:: ``Id`` Field Exclusion |
| 162 | + |
| 163 | + When you create a projection using a lambda expression, the output |
| 164 | + automatically excludes the ``Id`` field unless you explicitly include |
| 165 | + is as a projection field. |
| 166 | + |
| 167 | +Define a Sort |
| 168 | +------------- |
| 169 | + |
| 170 | +The ``SortDefinitionBuilder`` class provides a type-safe interface for |
| 171 | +building up sort syntax. Suppose you want to define a sort with the |
| 172 | +following order: |
| 173 | + |
| 174 | +- Ascending on ``Price`` |
| 175 | +- Descending on ``Category`` |
| 176 | + |
| 177 | +Use builders to create the sort definition with the typed variant: |
| 178 | + |
| 179 | +.. code-block:: csharp |
| 180 | + :copyable: true |
| 181 | + |
| 182 | + var builder = Builders<Flower>.Sort; |
| 183 | + var sort = builder.Ascending(f => f.Price).Descending(f => f.Category); |
| 184 | + |
| 185 | +Alternatively, you can use string-based field names to define the sort: |
| 186 | + |
| 187 | +.. code-block:: csharp |
| 188 | + :copyable: true |
| 189 | + |
| 190 | + var builder = Builders<Flower>.Sort; |
| 191 | + var sort = builder.Ascending("Price").Descending("Category"); |
| 192 | + |
| 193 | +Define an Update |
| 194 | +---------------- |
| 195 | + |
| 196 | +The ``UpdateDefinitionBuilder`` class provides a type-safe interface for |
| 197 | +building up an update specification. Suppose you want to create an |
| 198 | +update specification with the following criteria: |
| 199 | + |
| 200 | +- Create the new field ``SunRequirement`` |
| 201 | +- Multiply the ``Price`` field value by 0.9 |
| 202 | + |
| 203 | +Use builders to create the update specification with the typed variant: |
| 204 | + |
| 205 | +.. code-block:: csharp |
| 206 | + :copyable: true |
| 207 | + |
| 208 | + var builder = Builders<Flower>.Update; |
| 209 | + var update = builder.Set(f => f.SunRequirement, "Full sun").Mul(f => f.Price, 0.9); |
| 210 | + |
| 211 | +Alternatively, you can use string-based field names to define the update: |
| 212 | + |
| 213 | +.. code-block:: csharp |
| 214 | + :copyable: true |
| 215 | + |
| 216 | + var builder = Builders<Flower>.Update; |
| 217 | + var update = builder.Set("SunRequirement", "Full sun").Mul("Price", 0.9); |
| 218 | + |
| 219 | +Define Index Keys |
| 220 | +----------------- |
| 221 | + |
| 222 | +The ``IndexKeysDefinitionBuilder`` class provides a type-safe interface for |
| 223 | +defining index keys. Suppose you want to select ``Category`` as an |
| 224 | +ascending index key. |
| 225 | + |
| 226 | +Use builders to select the index key with the typed variant: |
| 227 | + |
| 228 | +.. code-block:: csharp |
| 229 | + :copyable: true |
| 230 | + |
| 231 | + var builder = Builders<Flower>.IndexKeys; |
| 232 | + var keys = builder.Ascending(f => f.Category); |
| 233 | + |
| 234 | +Alternatively, you can use string-based field names to select the index key: |
| 235 | + |
| 236 | +.. code-block:: csharp |
| 237 | + :copyable: true |
| 238 | + |
| 239 | + var builder = Builders<BsonDocument>.IndexKeys; |
| 240 | + var keys = builder.Ascending("Category"); |
| 241 | + |
| 242 | +The ``IndexKeysDefinitionBuilder`` class also provides methods to build |
| 243 | +a wildcard index. You can create a wildcard index using ``All field paths`` or ``A |
| 244 | +single field path``, in this case using ``Category``: |
| 245 | + |
| 246 | +.. tabs:: |
| 247 | + |
| 248 | + .. tab:: ``All field paths`` |
| 249 | + :tabid: all-wildcard-index |
| 250 | + |
| 251 | + .. code-block:: csharp |
| 252 | + :copyable: true |
| 253 | + |
| 254 | + var builder = Builders<Flower>.IndexKeys; |
| 255 | + var keys = builder.Wildcard(); |
| 256 | + |
| 257 | + .. tab:: ``A single field path`` |
| 258 | + :tabid: single-wildcard-index |
| 259 | + |
| 260 | + .. code-block:: csharp |
| 261 | + :copyable: true |
| 262 | + |
| 263 | + var builder = Builders<Flower>.IndexKeys; |
| 264 | + |
| 265 | + // Using the typed variant |
| 266 | + var keys = builder.Wildcard(f => f.Category); |
| 267 | + |
| 268 | + // Using string-based field names |
| 269 | + var keys = builder.Wildcard("Category"); |
| 270 | + |
| 271 | +Additional Information |
| 272 | +---------------------- |
| 273 | + |
| 274 | +Find runnable examples using builders for various operations under |
| 275 | +:ref:`Usage Examples <csharp-usage-examples>`. |
| 276 | + |
| 277 | +API Documentation |
| 278 | +~~~~~~~~~~~~~~~~~ |
| 279 | + |
| 280 | +To learn more about any of the methods or types discussed in this |
| 281 | +guide, see the following API Documentation: |
| 282 | + |
| 283 | +- `FilterDefinitionBuilder <{+api-root+}/T_MongoDB_Driver_FilterDefinitionBuilder_1.htm>`__ |
| 284 | +- `ProjectionDefinitionBuilder <{+api-root+}/T_MongoDB_Driver_ProjectionDefinitionBuilder_1.htm>`__ |
| 285 | +- `SortDefinitionBuilder <{+api-root+}/T_MongoDB_Driver_SortDefinitionBuilder_1.htm>`__ |
| 286 | +- `UpdateDefinitionBuilder <{+api-root+}/T_MongoDB_Driver_UpdateDefinitionBuilder_1.htm>`__ |
| 287 | +- `IndexKeysDefinitionBuilder <{+api-root+}/T_MongoDB_Driver_IndexKeysDefinitionBuilder_1.htm>`__ |
0 commit comments