Skip to content

Commit 323007d

Browse files
authored
[Rust] use structs to model data instead of Document in CRUD fundamentals (#95)
1 parent e570edd commit 323007d

File tree

8 files changed

+242
-124
lines changed

8 files changed

+242
-124
lines changed

source/fundamentals/crud/read-operations/cursor.txt

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
Access Data by Using a Cursor
55
=============================
66

7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: loop, retrieve, process, batch
13+
714
.. contents:: On this page
815
:local:
916
:backlinks: none
@@ -53,16 +60,13 @@ This guide includes the following sections:
5360
Sample Data for Examples
5461
------------------------
5562

56-
The examples in this guide use the following sample documents. Each
57-
document describes a fruit:
63+
The examples in this guide use the following data stored in a struct:
5864

59-
.. code-block:: json
60-
:copyable: false
61-
62-
{ "name": "strawberry", "color": "red" },
63-
{ "name": "banana", "color": "yellow" },
64-
{ "name": "pomegranate", "color": "red" },
65-
{ "name": "pineapple", "color": "yellow" }
65+
.. literalinclude:: /includes/fundamentals/code-snippets/crud/cursor.rs
66+
:language: rust
67+
:dedent:
68+
:start-after: start-sample-data
69+
:end-before: end-sample-data
6670

6771
.. _rust-cursor-individual:
6872

@@ -130,8 +134,8 @@ collection:
130134
:language: console
131135
:visible: false
132136

133-
Document({"_id": ObjectId("..."), "name": String("strawberry"), "color": String("red")})
134-
Document({"_id": ObjectId("..."), "name": String("pomegranate"), "color": String("red")})
137+
Fruit { name: "strawberry", color: "red" }
138+
Fruit { name: "pomegranate", color: "red" }
135139

136140
.. _rust-cursor-indiv-stream:
137141

@@ -178,12 +182,12 @@ collection:
178182
:visible: false
179183

180184
Output from next() iteration:
181-
{ "_id": ObjectId("..."), "name": "strawberry", "color": "red" }
182-
{ "_id": ObjectId("..."), "name": "pomegranate", "color": "red" }
183-
185+
Fruit { name: "strawberry", color: "red" }
186+
Fruit { name: "pomegranate", color: "red" }
187+
184188
Output from try_next() iteration:
185-
{ "_id": ObjectId("..."), "name": "banana", "color": "yellow" }
186-
{ "_id": ObjectId("..."), "name": "pineapple", "color": "yellow" }
189+
Fruit { name: "banana", color: "yellow" }
190+
Fruit { name: "pineapple", color: "yellow" }
187191

188192
.. _rust-cursor-array:
189193

@@ -220,10 +224,10 @@ You can use the following methods to retrieve documents as an array:
220224
:visible: false
221225

222226
Output from collect():
223-
[Ok(Document({"_id": ObjectId("..."), "name": String("strawberry"), "color": String("red")})), Ok(Document({"_id": ObjectId("..."), "name": String("pomegranate"), "color": String("red")}))]
224-
227+
[Ok(Fruit { name: "strawberry", color: "red" }), Ok(Fruit { name: "pomegranate", color: "red" })]
228+
225229
Output from try_collect():
226-
[Document({"_id": ObjectId("..."), "name": String("banana"), "color": String("yellow")}), Document({"_id": ObjectId("..."), "name": String("pineapple"), "color": String("yellow")})]
230+
[Fruit { name: "banana", color: "yellow" }, Fruit { name: "pineapple", color: "yellow" }]
227231

228232
.. warning:: Avoid Exceeding Application Memory Limits
229233

source/fundamentals/crud/read-operations/query.txt

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,22 @@ Sample Data
9494
The examples in this guide use the following sample documents. Each
9595
document represents a fruit in a store's inventory and contains
9696
information about its quantity. Some documents contain additional fields
97-
that describe the fruit or its vendors:
97+
that describe the fruit or its vendors.
9898

99+
.. literalinclude:: /includes/fundamentals/code-snippets/crud/query.rs
100+
:language: rust
101+
:dedent:
102+
:start-after: begin-data-struct
103+
:end-before: end-data-struct
99104

100-
.. code-block:: json
101-
:copyable: true
105+
The examples in the following sections query a collection of documents described by
106+
``Fruit`` structs:
102107

103-
{ "_id": 1, "name": "orange", "quantity": 7 },
104-
{ "_id": 2, "name": "apple", "quantity": 4, "description": "Granny Smith" },
105-
{ "_id": 3, "name": "banana", "quantity": 36 },
106-
{ "_id": 4, "name": "pear", "quantity": 28, "vendors": ["A", "C" ] }
108+
.. literalinclude:: /includes/fundamentals/code-snippets/crud/query.rs
109+
:language: rust
110+
:dedent:
111+
:start-after: begin-sample-docs
112+
:end-before: end-sample-docs
107113

108114
.. _rust-literal-values:
109115

@@ -128,8 +134,7 @@ that has the value of ``"pear"``:
128134
:language: json
129135
:visible: false
130136

131-
Document({"_id": Int32(4), "name": String("pear"), "quantity":
132-
Int32(28), "vendors": Array([String("A"), String("C")])})
137+
Fruit { _id: "4", name: "pear", quantity: 28, description: None, vendors: Some(["A", "C"]) }
133138

134139
.. note::
135140

@@ -178,12 +183,9 @@ documents with a ``quantity`` value greater than ``5``:
178183
:language: json
179184
:visible: false
180185

181-
Document({"_id": Int32(1), "name": String("orange"), "quantity":
182-
Int32(7)})
183-
Document({"_id": Int32(3), "name": String("banana"), "quantity":
184-
Int32(36)})
185-
Document({"_id": Int32(4), "name": String("pear"), "quantity":
186-
Int32(28), "vendors": Array([String("A"), String("C")])})
186+
Fruit { _id: "1", name: "orange", quantity: 7, description: None, vendors: None }
187+
Fruit { _id: "3", name: "banana", quantity: 36, description: None, vendors: None }
188+
Fruit { _id: "4", name: "pear", quantity: 28, description: None, vendors: Some(["A", "C"]) }
187189

188190
For more information on comparison operators, see :manual:`Comparison
189191
Query Operators </reference/operator/query-comparison/>` in the Server manual.
@@ -219,8 +221,7 @@ divisible by ``3``:
219221
:language: json
220222
:visible: false
221223

222-
Document({"_id": Int32(3), "name": String("banana"), "quantity":
223-
Int32(36)})
224+
Fruit { _id: "3", name: "banana", quantity: 36, description: None, vendors: None }
224225

225226
.. note::
226227

@@ -276,8 +277,17 @@ field:
276277
:language: json
277278
:visible: false
278279

279-
Document({"_id": Int32(2), "name": String("apple"), "quantity":
280-
Int32(4), "description": String("Granny Smith")})
280+
Fruit { _id: "2", name: "apple", quantity: 4, description: Some("Granny Smith"),
281+
vendors: None }
282+
283+
.. note::
284+
The :ref:`Fruit struct describing the documents<rust-query-sample-data>` in this guide
285+
uses the ``#[serde(skip_serializing_if = "Option::is_none")]`` attribute on two of its
286+
fields. This attribute specifies that the field be ignored if its value is ``None``. This
287+
prevents a ``description`` value of ``None`` from being returned on an ``$exists`` query.
288+
289+
See the `serialize_with <https://serde.rs/field-attrs.html#serialize_with>`__ Serde
290+
attribute for more information.
281291

282292
For a full list of element operators, see :manual:`Element
283293
Query Operators </reference/operator/query-element/>` in the Server manual.
@@ -312,8 +322,7 @@ for documents with a ``quantity`` value that is divisible by 3:
312322
:language: json
313323
:visible: false
314324

315-
Document({"_id": Int32(3), "name": String("banana"), "quantity":
316-
Int32(36)})
325+
Fruit { _id: "3", name: "banana", quantity: 36, description: None, vendors: None }
317326

318327
For a full list of evaluation operators, see :manual:`Evaluation
319328
Query Operators </reference/operator/query-evaluation/>` in the Server manual.
@@ -347,8 +356,7 @@ bits set as ``7``, which is equivalent to ``00000111`` in binary:
347356
:language: json
348357
:visible: false
349358

350-
Document({"_id": Int32(1), "name": String("orange"), "quantity":
351-
Int32(7)})
359+
Fruit { _id: "1", name: "orange", quantity: 7, description: None, vendors: None }
352360

353361
For a full list of bitwise operators, see :manual:`Bitwise
354362
Query Operators </reference/operator/query-bitwise/>` in the Server manual.
@@ -381,8 +389,7 @@ contains ``"C"``:
381389
:language: json
382390
:visible: false
383391

384-
Document({"_id": Int32(4), "name": String("pear"), "quantity":
385-
Int32(28), "vendors": Array([String("A"), String("C")])})
392+
Fruit { _id: "4", name: "pear", quantity: 28, description: None, vendors: Some(["A", "C"]) }
386393

387394
For a full list of bitwise operators, see :manual:`Array
388395
Query Operators </reference/operator/query-array/>` in the Server manual.

source/fundamentals/crud/read-operations/retrieve.txt

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,11 @@ The examples in this guide use the following sample documents. Each
5353
document represents an item in a store's inventory and contains
5454
information about its categorization and unit price:
5555

56-
.. code-block:: json
57-
:copyable: false
58-
59-
{ "item": "candle", "category": "decor", "unit_price": 2.89 },
60-
{ "item": "blender", "category": "kitchen", "unit_price": 38.49 },
61-
{ "item": "placemat", "category": "kitchen", "unit_price": 3.19 },
62-
{ "item": "watering can", "category": "garden", "unit_price": 11.99 }
56+
.. literalinclude:: /includes/fundamentals/code-snippets/crud/retrieve.rs
57+
:language: rust
58+
:dedent:
59+
:start-after: start-sample
60+
:end-before: end-sample
6361

6462
.. _rust-retrieve-find:
6563

@@ -225,8 +223,8 @@ following parameters:
225223
:language: console
226224
:visible: false
227225

228-
{ "_id": { ... }, "item": "watering can", "category": "garden", "unit_price": 11.99 }
229-
{ "_id": { ... }, "item": "candle", "category": "decor", "unit_price": 2.89 }
226+
Inventory { item: "watering can", category: "garden", unit_price: 11.99 }
227+
Inventory { item: "candle", category: "decor", unit_price: 2.89 }
230228

231229
.. _rust-find-one-example:
232230

@@ -254,20 +252,11 @@ following parameters:
254252
:visible: false
255253

256254
Some(
257-
Document({
258-
"_id": ObjectId(
259-
"...",
260-
),
261-
"item": String(
262-
"watering can",
263-
),
264-
"category": String(
265-
"garden",
266-
),
267-
"unit_price": Double(
268-
11.99,
269-
),
270-
}),
255+
Inventory {
256+
item: "watering can",
257+
category: "garden",
258+
unit_price: 11.99,
259+
},
271260
)
272261

273262
.. _rust-retrieve-aggregation:
@@ -390,9 +379,9 @@ pipeline that contains the following stages:
390379
:language: console
391380
:visible: false
392381

393-
{ "_id": { "category": "garden" }, "avg_price": 11.99 }
394-
{ "_id": { "category": "decor" }, "avg_price": 2.89 }
395-
{ "_id": { "category": "kitchen" }, "avg_price": 20.84 }
382+
Document({"_id": Document({"category": String("decor")}), "avg_price": Double(2.890000104904175)})
383+
Document({"_id": Document({"category": String("kitchen")}), "avg_price": Double(20.840000867843628)})
384+
Document({"_id": Document({"category": String("garden")}), "avg_price": Double(11.989999771118164)})
396385

397386
.. _rust-crud-retrieve-addtl-info:
398387

source/fundamentals/crud/write-operations/insert.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ document into the ``books`` collection:
105105
:language: console
106106
:visible: false
107107

108-
Inserted document with _id: ObjectId("...")
108+
Inserted document with _id: 8
109109

110110
.. include:: /includes/fundamentals/automatic-creation.rst
111111

@@ -202,9 +202,9 @@ multiple documents into the ``books`` collection:
202202
:visible: false
203203

204204
Inserted documents with _ids:
205-
ObjectId("...")
206-
ObjectId("...")
207-
ObjectId("...")
205+
Int32(5)
206+
Int32(6)
207+
Int32(7)
208208

209209
.. include:: /includes/fundamentals/automatic-creation.rst
210210

source/includes/fundamentals/code-snippets/crud/cursor.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
1-
use bson::Document;
21
use futures::{ StreamExt, TryStreamExt };
3-
use mongodb::{ bson::doc, Client, error::Result, options::{ FindOptions, CursorType } };
2+
use mongodb::{ bson::doc, bson::Document, Client, Collection, error::Result, options::{ FindOptions, CursorType } };
3+
4+
use serde::{ Deserialize, Serialize };
5+
6+
#[derive(Serialize, Deserialize, Debug)]
7+
struct Fruit {
8+
name: String,
9+
color: String
10+
}
411

512
#[tokio::main]
6-
async fn main() -> Result<()> {
13+
async fn main() -> mongodb::error::Result<()> {
14+
// Replace the placeholder with your Atlas connection string
715
let uri = "<connection string>";
16+
817
let client = Client::with_uri_str(uri).await?;
918

10-
let my_coll = client.database("db").collection::<Document>("fruits");
19+
let my_coll: Collection<Fruit> = client.database("db").collection("fruits");
20+
21+
//start-sample-data
22+
let docs = vec! [
23+
Fruit {
24+
name: "strawberry".to_string(),
25+
color: "red".to_string()
26+
},
27+
Fruit {
28+
name: "banana".to_string(),
29+
color: "yellow".to_string()
30+
},
31+
Fruit {
32+
name: "pomegranate".to_string(),
33+
color: "red".to_string()
34+
},
35+
Fruit {
36+
name: "pineapple".to_string(),
37+
color: "yellow".to_string()
38+
}
39+
];
40+
//end-sample-data
41+
42+
// Inserts sample documents into the collection
43+
let insert_many_result = my_coll.insert_many(docs, None).await?;
1144

1245
// start-indiv-builtin
1346
let mut cursor = my_coll.find(doc! { "color": "red" }, None).await?;
1447
while cursor.advance().await? {
15-
println!("{}", cursor.deserialize_current()?);
48+
println!("{:?}", cursor.deserialize_current()?);
1649
}
1750
// end-indiv-builtin
1851

@@ -22,14 +55,14 @@ async fn main() -> Result<()> {
2255
let mut cursor = my_coll.find(doc! { "color": "red" }, None).await?;
2356
println!("Output from next() iteration:");
2457
while let Some(doc) = cursor.next().await {
25-
println!("{}", doc?);
58+
println!("{:?}", doc?);
2659
}
2760

2861
println!();
2962
let mut cursor = my_coll.find(doc! { "color": "yellow" }, None).await?;
3063
println!("Output from try_next() iteration:");
3164
while let Some(doc) = cursor.try_next().await? {
32-
println!("{}", doc);
65+
println!("{:?}", doc);
3366
}
3467
// end-indiv-stream
3568

@@ -38,13 +71,13 @@ async fn main() -> Result<()> {
3871
// start-array
3972
let cursor = my_coll.find(doc! { "color": "red" }, None).await?;
4073
println!("Output from collect():");
41-
let v: Vec<Result<Document>> = cursor.collect().await;
74+
let v: Vec<Result<Fruit>> = cursor.collect().await;
4275
println!("{:?}", v);
4376

4477
println!();
4578
let cursor = my_coll.find(doc! { "color": "yellow" }, None).await?;
4679
println!("Output from try_collect():");
47-
let v: Vec<Document> = cursor.try_collect().await?;
80+
let v: Vec<Fruit> = cursor.try_collect().await?;
4881
println!("{:?}", v);
4982
// end-array
5083

0 commit comments

Comments
 (0)