Skip to content

Commit b126d24

Browse files
authored
RUST-736 Update README examples to reflect usage of 2.0 API (#343)
1 parent e5ad490 commit b126d24

File tree

2 files changed

+152
-74
lines changed

2 files changed

+152
-74
lines changed

README.md

Lines changed: 81 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# MongoDB Rust Driver
22
[![Crates.io](https://img.shields.io/crates/v/mongodb.svg)](https://crates.io/crates/mongodb) [![docs.rs](https://docs.rs/mongodb/badge.svg)](https://docs.rs/mongodb) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
33

4-
This repository contains the officially supported MongoDB Rust driver, a client side library that can be used to interact with MongoDB deployments in Rust applications. It uses the [`bson`](https://docs.rs/bson) crate for BSON support. The driver contains a fully async API that supports either [`tokio`](https://crates.io/crates/tokio) (default) or [`async-std`](https://crates.io/crates/async-std), depending on the feature flags set. The driver also has a sync API that may be enabled via feature flag.
4+
This repository contains the officially supported MongoDB Rust driver, a client side library that can be used to interact with MongoDB deployments in Rust applications. It uses the [`bson`](https://docs.rs/bson/2.0.0-beta) crate for BSON support. The driver contains a fully async API that supports either [`tokio`](https://crates.io/crates/tokio) (default) or [`async-std`](https://crates.io/crates/async-std), depending on the feature flags set. The driver also has a sync API that may be enabled via feature flag.
55

66
## Index
77
- [Installation](#installation)
@@ -63,7 +63,7 @@ features = ["sync"]
6363
**Note:** if the sync API is enabled, the async-specific types will be privatized (e.g. `mongodb::Client`). The sync-specific types can be imported from `mongodb::sync` (e.g. `mongodb::sync::Client`).
6464

6565
## Example Usage
66-
Below are simple examples of using the driver. For more specific examples and the API reference, see the driver's [docs.rs page](https://docs.rs/mongodb).
66+
Below are simple examples of using the driver. For more specific examples and the API reference, see the driver's [docs.rs page](https://docs.rs/mongodb/2.0.0-beta).
6767

6868
### Using the async API
6969
#### Connecting to a MongoDB deployment
@@ -112,32 +112,64 @@ let docs = vec![
112112
// Insert some documents into the "mydb.books" collection.
113113
collection.insert_many(docs, None).await?;
114114
```
115+
116+
A [`Collection`](https://docs.rs/mongodb/2.0.0-beta/mongodb/struct.Collection.html) can be parameterized with any type that implements the `Serialize` and `Deserialize` traits from the [`serde`](https://serde.rs/) crate, not just `Document`:
117+
118+
``` toml
119+
# In Cargo.toml, add the following dependency.
120+
serde = { version = "1.0", features = ["derive"] }
121+
```
122+
123+
``` rust
124+
use serde::{Deserialize, Serialize};
125+
126+
#[derive(Debug, Serialize, Deserialize)]
127+
struct Book {
128+
title: String,
129+
author: String,
130+
}
131+
```
132+
133+
``` rust
134+
// Get a handle to a collection of `Book`.
135+
let typed_collection = db.collection::<Book>("books");
136+
137+
let books = vec![
138+
Book {
139+
title: "The Grapes of Wrath".to_string(),
140+
author: "John Steinbeck".to_string(),
141+
},
142+
Book {
143+
title: "To Kill a Mockingbird".to_string(),
144+
author: "Harper Lee".to_string(),
145+
},
146+
];
147+
148+
// Insert the books into "mydb.books" collection, no manual conversion to BSON necessary.
149+
typed_collection.insert_many(books, None).await?;
150+
```
151+
115152
#### Finding documents in a collection
153+
Results from queries are generally returned via [`Cursor`](https://docs.rs/mongodb/2.0.0-beta/mongodb/struct.Cursor.html), a struct which streams the results back from the server as requested. The [`Cursor`](https://docs.rs/mongodb/2.0.0-beta/mongodb/struct.Cursor.html) type implements the [`Stream`](https://docs.rs/futures/latest/futures/stream/index.html) trait from the [`futures`](https://crates.io/crates/futures) crate, and in order to access its streaming functionality you need to import at least one of the [`StreamExt`](https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html) or [`TryStreamExt`](https://docs.rs/futures/latest/futures/stream/trait.TryStreamExt.html) traits.
154+
155+
``` toml
156+
# In Cargo.toml, add the following dependency.
157+
futures = "0.3"
158+
```
116159
```rust
117-
use futures::stream::StreamExt;
118-
use mongodb::{
119-
bson::{doc, Bson},
120-
options::FindOptions,
121-
};
160+
// This trait is required to use `try_next()` on the cursor
161+
use futures::stream::TryStreamExt;
162+
use mongodb::{bson::doc, options::FindOptions};
122163
```
123164
```rust
124-
// Query the documents in the collection with a filter and an option.
165+
// Query the books in the collection with a filter and an option.
125166
let filter = doc! { "author": "George Orwell" };
126167
let find_options = FindOptions::builder().sort(doc! { "title": 1 }).build();
127-
let mut cursor = collection.find(filter, find_options).await?;
168+
let mut cursor = typed_collection.find(filter, find_options).await?;
128169

129170
// Iterate over the results of the cursor.
130-
while let Some(result) = cursor.next().await {
131-
match result {
132-
Ok(document) => {
133-
if let Some(title) = document.get("title").and_then(Bson::as_str) {
134-
println!("title: {}", title);
135-
} else {
136-
println!("no title found");
137-
}
138-
}
139-
Err(e) => return Err(e.into()),
140-
}
171+
while let Some(book) = cursor.try_next().await? {
172+
println!("title: {}", book.title);
141173
}
142174
```
143175

@@ -147,36 +179,43 @@ The driver also provides a blocking sync API. See the [Installation](#enabling-t
147179
The various sync-specific types are found in the `mongodb::sync` submodule rather than in the crate's top level like in the async API. The sync API calls through to the async API internally though, so it looks and behaves similarly to it.
148180
```rust
149181
use mongodb::{
150-
bson::{doc, Bson, Document},
182+
bson::doc,
151183
sync::Client,
152184
};
185+
use serde::{Deserialize, Serialize};
186+
187+
#[derive(Debug, Serialize, Deserialize)]
188+
struct Book {
189+
title: String,
190+
author: String,
191+
}
153192
```
154193
```rust
155194
let client = Client::with_uri_str("mongodb://localhost:27017")?;
156195
let database = client.database("mydb");
157-
let collection = database.collection::<Document>("books");
196+
let collection = database.collection::<Book>("books");
158197

159198
let docs = vec![
160-
doc! { "title": "1984", "author": "George Orwell" },
161-
doc! { "title": "Animal Farm", "author": "George Orwell" },
162-
doc! { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" },
199+
Book {
200+
title: "1984".to_string(),
201+
author: "George Orwell".to_string(),
202+
},
203+
Book {
204+
title: "Animal Farm".to_string(),
205+
author: "George Orwell".to_string(),
206+
},
207+
Book {
208+
title: "The Great Gatsby".to_string(),
209+
author: "F. Scott Fitzgerald".to_string(),
210+
},
163211
];
164212

165-
// Insert some documents into the "mydb.books" collection.
213+
// Insert some books into the "mydb.books" collection.
166214
collection.insert_many(docs, None)?;
167215

168216
let cursor = collection.find(doc! { "author": "George Orwell" }, None)?;
169217
for result in cursor {
170-
match result {
171-
Ok(document) => {
172-
if let Some(title) = document.get("title").and_then(Bson::as_str) {
173-
println!("title: {}", title);
174-
} else {
175-
println!("no title found");
176-
}
177-
}
178-
Err(e) => return Err(e.into()),
179-
}
218+
println!("title: {}", result?.title);
180219
}
181220
```
182221

@@ -194,6 +233,12 @@ On Windows, there is a known issue in the `trust-dns-resolver` crate, which the
194233

195234
e.g.
196235

236+
``` rust
237+
use mongodb::{
238+
options::{ClientOptions, ResolverConfig},
239+
Client,
240+
};
241+
```
197242
``` rust
198243
let options = ClientOptions::parse_with_resolver_config(
199244
"mongodb+srv://my.host.com",

tests/readme_examples.rs

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -64,71 +64,104 @@ async fn _inserting_documents_into_a_collection(db: mongodb::Database) -> Result
6464
Ok(())
6565
}
6666

67+
use serde::{Deserialize, Serialize};
68+
#[derive(Debug, Serialize, Deserialize)]
69+
struct Book {
70+
title: String,
71+
author: String,
72+
}
73+
74+
#[cfg(not(feature = "sync"))]
75+
async fn _inserting_documents_into_a_typed_collection(db: mongodb::Database) -> Result<()> {
76+
// Get a handle to a collection of `Book`.
77+
let typed_collection = db.collection::<Book>("books");
78+
79+
let books = vec![
80+
Book {
81+
title: "The Grapes of Wrath".to_string(),
82+
author: "John Steinbeck".to_string(),
83+
},
84+
Book {
85+
title: "To Kill a Mockingbird".to_string(),
86+
author: "Harper Lee".to_string(),
87+
},
88+
];
89+
90+
// Insert the books into "mydb.books" collection, no manual conversion to BSON necessary.
91+
typed_collection.insert_many(books, None).await?;
92+
93+
Ok(())
94+
}
95+
6796
#[cfg(not(feature = "sync"))]
6897
async fn _finding_documents_into_a_collection(
69-
collection: mongodb::Collection<mongodb::bson::Document>,
98+
typed_collection: mongodb::Collection<Book>,
7099
) -> Result<()> {
71-
use futures::stream::StreamExt;
72-
use mongodb::{
73-
bson::{doc, Bson},
74-
options::FindOptions,
75-
};
100+
// This trait is required to use `try_next()` on the cursor
101+
use futures::stream::TryStreamExt;
102+
use mongodb::{bson::doc, options::FindOptions};
76103

77-
// Query the documents in the collection with a filter and an option.
104+
// Query the books in the collection with a filter and an option.
78105
let filter = doc! { "author": "George Orwell" };
79106
let find_options = FindOptions::builder().sort(doc! { "title": 1 }).build();
80-
let mut cursor = collection.find(filter, find_options).await?;
107+
let mut cursor = typed_collection.find(filter, find_options).await?;
81108

82109
// Iterate over the results of the cursor.
83-
while let Some(result) = cursor.next().await {
84-
match result {
85-
Ok(document) => {
86-
if let Some(title) = document.get("title").and_then(Bson::as_str) {
87-
println!("title: {}", title);
88-
} else {
89-
println!("no title found");
90-
}
91-
}
92-
Err(e) => return Err(e.into()),
93-
}
110+
while let Some(book) = cursor.try_next().await? {
111+
println!("title: {}", book.title);
94112
}
95113

96114
Ok(())
97115
}
98116

99117
#[cfg(feature = "sync")]
100118
async fn _using_the_sync_api() -> Result<()> {
101-
use mongodb::{
102-
bson::{doc, Bson, Document},
103-
sync::Client,
104-
};
119+
use mongodb::{bson::doc, sync::Client};
105120

106121
let client = Client::with_uri_str("mongodb://localhost:27017")?;
107122
let database = client.database("mydb");
108-
let collection = database.collection::<Document>("books");
123+
let collection = database.collection::<Book>("books");
109124

110125
let docs = vec![
111-
doc! { "title": "1984", "author": "George Orwell" },
112-
doc! { "title": "Animal Farm", "author": "George Orwell" },
113-
doc! { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" },
126+
Book {
127+
title: "1984".to_string(),
128+
author: "George Orwell".to_string(),
129+
},
130+
Book {
131+
title: "Animal Farm".to_string(),
132+
author: "George Orwell".to_string(),
133+
},
134+
Book {
135+
title: "The Great Gatsby".to_string(),
136+
author: "F. Scott Fitzgerald".to_string(),
137+
},
114138
];
115139

116-
// Insert some documents into the "mydb.books" collection.
140+
// Insert some books into the "mydb.books" collection.
117141
collection.insert_many(docs, None)?;
118142

119143
let cursor = collection.find(doc! { "author": "George Orwell" }, None)?;
120144
for result in cursor {
121-
match result {
122-
Ok(document) => {
123-
if let Some(title) = document.get("title").and_then(Bson::as_str) {
124-
println!("title: {}", title);
125-
} else {
126-
println!("no title found");
127-
}
128-
}
129-
Err(e) => return Err(e.into()),
130-
}
145+
println!("title: {}", result?.title);
131146
}
132147

133148
Ok(())
134149
}
150+
151+
#[cfg(not(feature = "sync"))]
152+
async fn _windows_dns_note() -> Result<()> {
153+
use mongodb::{
154+
options::{ClientOptions, ResolverConfig},
155+
Client,
156+
};
157+
158+
let options = ClientOptions::parse_with_resolver_config(
159+
"mongodb+srv://my.host.com",
160+
ResolverConfig::cloudflare(),
161+
)
162+
.await?;
163+
let client = Client::with_options(options)?;
164+
165+
drop(client);
166+
Ok(())
167+
}

0 commit comments

Comments
 (0)