|
| 1 | +.. _rust-faq: |
| 2 | + |
| 3 | +=== |
| 4 | +FAQ |
| 5 | +=== |
| 6 | + |
| 7 | +.. facet:: |
| 8 | + :name: genre |
| 9 | + :values: reference |
| 10 | + |
| 11 | +.. meta:: |
| 12 | + :keywords: code example, connection error, question, help |
| 13 | + |
| 14 | +.. contents:: On this page |
| 15 | + :local: |
| 16 | + :backlinks: none |
| 17 | + :depth: 1 |
| 18 | + :class: singlecol |
| 19 | + |
| 20 | +On this page, you can find frequently asked questions and their corresponding answers. |
| 21 | + |
| 22 | +.. tip:: |
| 23 | + |
| 24 | + If you can't find an answer to your question on this page, see the |
| 25 | + :ref:`rust-issues-and-help` page for information on how to report issues. |
| 26 | + |
| 27 | +Why Do I Get Errors While Connecting to MongoDB? |
| 28 | +------------------------------------------------ |
| 29 | + |
| 30 | +If you have trouble connecting to a MongoDB deployment, see the |
| 31 | +:ref:`rust-connection-troubleshooting` guide for possible solutions. |
| 32 | + |
| 33 | +.. _rust-faq-connection-pool: |
| 34 | + |
| 35 | +How Does Connection Pooling Work in the Rust Driver? |
| 36 | +---------------------------------------------------- |
| 37 | + |
| 38 | +Each server in your MongoDB cluster maintains a connection pool. You can access or |
| 39 | +manage the behavior of the connection pool by using an instance of a `Client |
| 40 | +<{+api+}/struct.Client.html>`__. Connection pools open sockets on demand to support |
| 41 | +concurrent operations in your multi-threaded application. |
| 42 | + |
| 43 | +You can configure the following connection pool features: |
| 44 | + |
| 45 | +- Maximum and minimum size, set by the ``max_pool_size`` and ``min_pool_size`` options |
| 46 | +- Maximum number of connections that the pool creates in parallel, set by the ``max_connecting`` |
| 47 | + option |
| 48 | +- Maximum idle time, set by the ``max_idle_time`` option |
| 49 | + |
| 50 | +For more information about connection pooling, see the :ref:`rust-performance-pool` |
| 51 | +section of the Performance Considerations guide. |
| 52 | + |
| 53 | +How Do I Convert Between BSON and Rust Types? |
| 54 | +--------------------------------------------- |
| 55 | + |
| 56 | +The {+driver-short+} and the BSON library use the Serde framework to perform |
| 57 | +conversions between custom Rust types and BSON. You can add the ``serde`` |
| 58 | +crate to your ``Cargo.toml`` file to access the functionality of the Serde framework. |
| 59 | +For instructions on adding this crate, see `serde <https://crates.io/crates/serde>`__ |
| 60 | +in the crates registry. |
| 61 | + |
| 62 | +After you add the crate to your application, you can model the documents in a collection |
| 63 | +by using a custom type instead of a BSON document. The following example includes the ``derive`` |
| 64 | +attribute before the ``Vegetable`` struct definition, which instructs the driver to |
| 65 | +perform the following actions when needed: |
| 66 | + |
| 67 | +- Serialize the struct, which converts the struct to BSON |
| 68 | +- Deserialize BSON, which converts BSON data to your struct |
| 69 | + |
| 70 | +.. code-block:: rust |
| 71 | + :copyable: true |
| 72 | + |
| 73 | + #[derive(Serialize, Deserialize)] |
| 74 | + struct Vegetable { |
| 75 | + // Add struct fields here |
| 76 | + } |
| 77 | + |
| 78 | +You can then create a ``Collection`` instance with your custom struct type as its |
| 79 | +generic type parameter. The following example assigns a ``Collection`` instance |
| 80 | +parameterized with the ``Vegetable`` type to the ``my_coll`` variable: |
| 81 | + |
| 82 | +.. code-block:: rust |
| 83 | + :copyable: true |
| 84 | + |
| 85 | + let my_coll: Collection<Vegetable> = client.database("db").collection("vegetables"); |
| 86 | + |
| 87 | +For more information about converting between BSON and Rust types, see the |
| 88 | +:ref:`rust-serialization` guide and the :website:`Structuring Data with Serde in Rust |
| 89 | +</developer/languages/rust/serde-improvements/>` MongoDB Developer Center article. |
| 90 | + |
| 91 | +How Do I Fix Unsatisfied Trait Bounds Errors? |
| 92 | +--------------------------------------------- |
| 93 | + |
| 94 | +Trait bounds allow methods to restrict which types they accept as parameters |
| 95 | +and what functionality those types must implement. For example, if you define |
| 96 | +a method that accepts a generic type parameter and prints its value, the parameter |
| 97 | +must implement the ``Display`` trait for printing purposes. The following example |
| 98 | +defines the ``printer()`` method and specifies that its parameter must implement |
| 99 | +``Display``: |
| 100 | + |
| 101 | +.. code-block:: rust |
| 102 | + :copyable: true |
| 103 | + |
| 104 | + fn printer<T: Display>(t: T) { |
| 105 | + println!("{}", t); |
| 106 | + } |
| 107 | + |
| 108 | +When calling a method on a data type, you might encounter an error stating that |
| 109 | +the method's trait bounds are not satisfied. For example, the driver might raise |
| 110 | +the following error message when you call the ``try_next()`` method on a ``Cursor`` |
| 111 | +instance: |
| 112 | + |
| 113 | +.. code-block:: none |
| 114 | + :copyable: false |
| 115 | + |
| 116 | + error[E0599]: the method `try_next` exists for struct `mongodb::Cursor<T>`, |
| 117 | + but its trait bounds were not satisfied |
| 118 | + |
| 119 | +The ``Cursor<T>`` type only implements the ``Stream`` trait, which is required to access |
| 120 | +the ``try_next()`` method, if the trait bounds for ``T`` are satisfied. Namely, ``T`` |
| 121 | +must implement the ``DeserializeOwned`` trait, as specified in the `Cursor |
| 122 | +<{+api+}/struct.Cursor.html>`__ API documentation. The following example replicates the |
| 123 | +preceding error message by defining a custom ``Actor`` struct to model documents in the |
| 124 | +``actors`` collection. However, this struct does not implement the ``DeserializeOwned`` trait, |
| 125 | +and using the ``try_next()`` method to iterate over ``Actor`` instances causes an error: |
| 126 | + |
| 127 | +.. code-block:: rust |
| 128 | + :copyable: true |
| 129 | + |
| 130 | + struct Actor { |
| 131 | + name: String, |
| 132 | + } |
| 133 | + |
| 134 | + // Add setup code here |
| 135 | + |
| 136 | + let my_coll: Collection<Actor> = client.database("db").collection("actors"); |
| 137 | + let mut cursor = my_coll.find(None, None).await?; |
| 138 | + while let Some(result) = cursor.try_next().await? { |
| 139 | + println!("{:?}", result); |
| 140 | + }; |
| 141 | + |
| 142 | +To resolve the trait bounds error, identify the data type over which the cursor |
| 143 | +iterates and ensure that this data type implements the ``DeserializeOwned`` trait. |
| 144 | +You can use the ``derive`` attribute to apply the required trait bound. |
| 145 | + |
| 146 | +.. note:: Deserialize and DeserializeOwned Traits |
| 147 | + |
| 148 | + The ``serde`` crate provides derive macros to generate the implementation of |
| 149 | + certain traits, including the ``Deserialize`` trait. However, this crate does not |
| 150 | + offer a derive macro for the ``DeserializeOwned`` trait. Data types that implement |
| 151 | + ``Deserialize`` without lifetime restrictions automatically implement ``DeserializeOwned``, |
| 152 | + so you can implement ``Deserialize`` to fulfill the ``DeserializeOwned`` trait bound. |
| 153 | + |
| 154 | +The following example adjusts the ``Actor`` struct definition to implement ``Deserialize``: |
| 155 | + |
| 156 | +.. code-block:: rust |
| 157 | + :copyable: true |
| 158 | + |
| 159 | + #[derive(Deserialize)] |
| 160 | + struct Actor { |
| 161 | + name: String, |
| 162 | + } |
| 163 | + |
| 164 | +For more information about trait bounds, see the following resources: |
| 165 | + |
| 166 | +- :community-forum:`Cursor trait bounds question <t/rust-driver-help-writing-a-generic-find-method/168846>` |
| 167 | + in the Community Forums |
| 168 | +- `Bounds <https://doc.rust-lang.org/rust-by-example/generics/bounds.html>`__ in the |
| 169 | + Rust language documentation |
| 170 | +- `Derive <https://doc.rust-lang.org/rust-by-example/trait/derive.html>`__ |
| 171 | + in the Rust language documentation |
| 172 | + |
| 173 | +How Do I Process a Value Wrapped in a Result or Option Enum? |
| 174 | +------------------------------------------------------------ |
| 175 | + |
| 176 | +Rust provides the ``Result`` and ``Option`` enums as safeguards for your application |
| 177 | +code. Many methods offered by the {+driver-short+} return values wrapped in one of these |
| 178 | +two types. |
| 179 | + |
| 180 | +The ``Result`` enum can return the following variants: |
| 181 | + |
| 182 | +- ``Ok(T)``: wraps the value of the result of the operation |
| 183 | +- ``Err(E)``: wraps an error value if the operation is unsuccessful |
| 184 | + |
| 185 | +For example, the ``insert_one()`` method returns a ``Result`` type to wrap either a successful |
| 186 | +response or an error. |
| 187 | + |
| 188 | +To access the unwrapped result of ``insert_one()``, use the ``?`` operator. If the operation is |
| 189 | +successful, the method returns the ``Ok(InsertOneResult)`` variant of the ``Result`` enum. In this |
| 190 | +case, the ``?`` operator unwraps the ``InsertOneResult`` value and assigns it to the ``insert_one_result`` |
| 191 | +variable. If the operation is unsuccessful, the method returns the ``Err(E)`` enum variant, and the |
| 192 | +``?`` operator unwraps and returns the error value. The following code demonstrates the syntax for |
| 193 | +using the ``?`` operator while handling an insert operation result: |
| 194 | + |
| 195 | +.. code-block:: rust |
| 196 | + :copyable: true |
| 197 | + |
| 198 | + let insert_one_result = my_coll.insert_one(doc, None).await?; |
| 199 | + |
| 200 | +Alternatively, you can create a conditional to handle the unwrapped values of ``InsertOneResult``. |
| 201 | +The following code uses the ``match`` keyword to process the ``insert_one()`` result: |
| 202 | + |
| 203 | +.. code-block:: rust |
| 204 | + :copyable: true |
| 205 | + |
| 206 | + let insert_one_result = my_coll.insert_one(doc, None).await; |
| 207 | + |
| 208 | + match insert_one_result { |
| 209 | + Ok(val) => { |
| 210 | + println!("Document inserted with ID: {}", val.inserted_id); |
| 211 | + }, |
| 212 | + Err(err) => { |
| 213 | + println!("Operation not successful"); |
| 214 | + } |
| 215 | + } |
| 216 | + |
| 217 | +The ``Option`` enum can return the following variants: |
| 218 | + |
| 219 | +- ``None``: represents an empty value returned by an operation |
| 220 | +- ``Some(T)``: wraps a non-empty return value |
| 221 | + |
| 222 | +Some {+driver-short+} methods return an ``Option`` type, such as the ``read_concern()`` |
| 223 | +method. This method returns an ``Option`` that wraps either an empty value, if no read |
| 224 | +concern exists, or a ``ReadConcern`` value. |
| 225 | + |
| 226 | +To access the result of ``read_concern()``, you can use the same ``match`` syntax as shown |
| 227 | +in the preceding example to process the ``None`` and ``Some(T)`` variants. Alternatively, you |
| 228 | +can use the ``if let`` syntax to process only the ``Some(T)`` variant. The following code unwraps |
| 229 | +and prints the non-empty ``read_concern()`` return value, if it exists: |
| 230 | + |
| 231 | +.. code-block:: rust |
| 232 | + :copyable: true |
| 233 | + |
| 234 | + if let Some(rc) = my_coll.read_concern() { |
| 235 | + println!("Read concern: {:?}", rc); |
| 236 | + } |
| 237 | + |
| 238 | +For more information about the ``Result`` and ``Option`` enums, see the following |
| 239 | +resources in the Rust language documentation: |
| 240 | + |
| 241 | +- `Result <https://doc.rust-lang.org/std/result/enum.Result.html>`__ |
| 242 | +- `Option <https://doc.rust-lang.org/std/option/enum.Option.html>`__ |
| 243 | +- `? Operator <https://doc.rust-lang.org/rust-by-example/std/result/question_mark.html>`__ |
| 244 | +- `Concise Control Flow with if let <https://doc.rust-lang.org/book/ch06-03-if-let.html>`__ |
0 commit comments