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
crate for BSON support. The driver contains a fully async API that supports either tokio
(default) or async-std
, depending on the feature flags set. The driver also has a sync API that may be enabled via feature flag.
- Installation
- Example Usage
- Platforms
- Atlas note
- Windows DNS note
- Bug Reporting / Feature Requests
- Contributing
- Running the tests
- Continuous Integration
- License
Driver Version | Required Rust Version |
---|---|
master | 1.45+ |
2.0.0-alpha | 1.45+ |
1.2.x | 1.43+ |
1.1.x | 1.43+ |
1.0.x | 1.43+ |
0.11.x | 1.43+ |
0.10.x | 1.43+ |
0.9.x | 1.39+ |
- MongoDB 3.6+
Note: A bug affecting Rust 1.46-1.47 may cause out-of-memory errors when compiling an application that uses the 1.1 version of the driver with a framework like actix-web. Upgrading Rust to 1.48+ or the driver to 1.2+ fixes this issue. For more information, see rust-lang/rust#75992.
The driver is available on crates.io. To use the driver in your application, simply add it to your project's Cargo.toml
.
[dependencies]
mongodb = "1.1.1"
The driver supports both of the most popular async runtime crates, namely tokio
and async-std
. By default, the driver will use tokio
, but you can explicitly choose a runtime by specifying one of "tokio-runtime"
or "async-std-runtime"
feature flags in your Cargo.toml
.
For example, to instruct the driver to work with async-std
, add the following to your Cargo.toml
:
[dependencies.mongodb]
version = "1.1.1"
default-features = false
features = ["async-std-runtime"]
The driver also provides a blocking sync API. To enable this, add the "sync"
feature to your Cargo.toml
:
[dependencies.mongodb]
version = "1.1.1"
default-features = false
features = ["sync"]
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
).
Below are simple examples of using the driver. For more specific examples and the API reference, see the driver's docs.rs page.
use mongodb::{Client, options::ClientOptions};
// Parse a connection string into an options struct.
let mut client_options = ClientOptions::parse("mongodb://localhost:27017").await?;
// Manually set an option.
client_options.app_name = Some("My App".to_string());
// Get a handle to the deployment.
let client = Client::with_options(client_options)?;
// List the names of the databases in that deployment.
for db_name in client.list_database_names(None, None).await? {
println!("{}", db_name);
}
// Get a handle to a database.
let db = client.database("mydb");
// List the names of the collections in that database.
for collection_name in db.list_collection_names(None).await? {
println!("{}", collection_name);
}
use mongodb::bson::doc;
// Get a handle to a collection in the database.
let collection = db.collection("books");
let docs = vec![
doc! { "title": "1984", "author": "George Orwell" },
doc! { "title": "Animal Farm", "author": "George Orwell" },
doc! { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" },
];
// Insert some documents into the "mydb.books" collection.
collection.insert_many(docs, None).await?;
use futures::stream::StreamExt;
use mongodb::{
bson::{doc, Bson},
options::FindOptions,
};
// Query the documents in the collection with a filter and an option.
let filter = doc! { "author": "George Orwell" };
let find_options = FindOptions::builder().sort(doc! { "title": 1 }).build();
let mut cursor = collection.find(filter, find_options).await?;
// Iterate over the results of the cursor.
while let Some(result) = cursor.next().await {
match result {
Ok(document) => {
if let Some(title) = document.get("title").and_then(Bson::as_str) {
println!("title: {}", title);
} else {
println!("no title found");
}
}
Err(e) => return Err(e.into()),
}
}
The driver also provides a blocking sync API. See the Installation section for instructions on how to enable it.
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.
use mongodb::{
bson::{doc, Bson},
sync::Client,
};
let client = Client::with_uri_str("mongodb://localhost:27017")?;
let database = client.database("mydb");
let collection = database.collection("books");
let docs = vec![
doc! { "title": "1984", "author": "George Orwell" },
doc! { "title": "Animal Farm", "author": "George Orwell" },
doc! { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" },
];
// Insert some documents into the "mydb.books" collection.
collection.insert_many(docs, None)?;
let cursor = collection.find(doc! { "author": "George Orwell" }, None)?;
for result in cursor {
match result {
Ok(document) => {
if let Some(title) = document.get("title").and_then(Bson::as_str) {
println!("title: {}", title);
} else {
println!("no title found");
}
}
Err(e) => return Err(e.into()),
}
}
The driver tests against Linux, MacOS, and Windows in CI.
Currently, the driver has issues connecting to Atlas tiers above M2 unless the server version is at least 4.2. We're working on fixing this, but in the meantime, a workaround is to upgrade your cluster to 4.2. The driver has no known issues with either M0 or M2 instances.
On Windows, there is a known issue in the trust-dns-resolver
crate, which the driver uses to perform DNS lookups, that causes severe performance degradation in resolvers that use the system configuration. Since the driver uses the system configuration by default, users are recommended to specify an alternate resolver configuration on Windows until that issue is resolved. This only has an effect when connecting to deployments using a mongodb+srv
connection string.
e.g.
let options = ClientOptions::parse_with_resolver_config(
"mongodb+srv://my.host.com",
ResolverConfig::cloudflare(),
)
.await?;
let client = Client::with_options(options)?;
To file a bug report or submit a feature request, please open a ticket on our Jira project:
- Create an account and login at jira.mongodb.org
- Navigate to the RUST project at jira.mongodb.org/browse/RUST
- Click Create Issue - If the ticket you are filing is a bug report, please include as much detail as possible about the issue and how to reproduce it.
Before filing a ticket, please use the search functionality of Jira to see if a similar issue has already been filed.
We encourage and would happily accept contributions in the form of GitHub pull requests. Before opening one, be sure to run the tests locally; check out the testing section for information on how to do that. Once you open a pull request, your branch will be run against the same testing matrix that we use for our continuous integration system, so it is usually sufficient to only run the integration tests locally against a standalone. Remember to always run the linter tests before opening a pull request.
In order to run the tests (which are mostly integration tests), you must have access to a MongoDB deployment. You may specify a MongoDB connection string in the MONGODB_URI
environment variable, and the tests will use it to connect to the deployment. If MONGODB_URI
is unset, the tests will attempt to connect to a local deployment on port 27017.
Note: The integration tests will clear out the databases/collections they need to use, but they do not clean up after themselves.
To actually run the tests, you can use cargo
like you would in any other crate:
cargo test --verbose # runs against localhost:27017
export MONGODB_URI="mongodb://localhost:123"
cargo test --verbose # runs against localhost:123
The authentication tests will only be included in the test run if certain requirements are met:
- The deployment must have
--auth
enabled - Credentials must be specified in
MONGODB_URI
- The credentials specified in
MONGODB_URI
must be valid and have root privileges on the deployment
export MONGODB_URI="mongodb://user:pass@localhost:27017"
cargo test --verbose # auth tests included
Certain tests will only be run against certain topologies. To ensure that the entire test suite is run, make sure to run the tests separately against standalone, replicated, and sharded deployments.
export MONGODB_URI="mongodb://my-standalone-host:20717" # mongod running on 27017
cargo test --verbose
export MONGODB_URI="mongodb://localhost:27018,localhost:27019,localhost:27020/?replSet=repl"
cargo test --verbose
export MONGODB_URI="mongodb://localhost:27021" # mongos running on 27021
cargo test --verbose
To run the tests with TLS/SSL enabled, you must enable it on the deployment and in MONGODB_URI
.
export MONGODB_URI="mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=cert.pem&tlsCAFile=ca.pem"
cargo test --verbose
Note: When you open a pull request, your code will be run against a comprehensive testing matrix, so it is usually not necessary to run the integration tests against all combinations of topology/auth/TLS locally.
Our linter tests use the nightly version of rustfmt
to verify that the source is formatted properly and the stable version of clippy
to statically detect any common mistakes.
You can use rustup
to install them both:
rustup component add clippy --toolchain stable
rustup component add rustfmt --toolchain nightly
Our linter tests also use rustdoc
to verify that all necessary documentation is present and properly formatted. rustdoc
is included in the standard Rust distribution.
To run the linter tests, run the check-clippy.sh
, check-rustfmt.sh
, and check-rustdoc.sh
scripts in the .evergreen
directory:
bash .evergreen/check-clippy.sh && bash .evergreen/check-rustfmt.sh && bash .evergreen/check-rustdoc.sh
Commits to master are run automatically on evergreen.
This project is licensed under the Apache License 2.0.