This is superseded by the official MongoDB Rust Driver

Overview

This Repository is NOT a supported MongoDB product

Travis Crates.io docs.rs License

MongoDB Rust Driver Prototype

NOTE: This driver is superseded by the official MongoDB Rust driver, and will no longer be updated.

This branch contains active development on a new driver written for Rust 1.x and MongoDB 3.0.x.

The API and implementation are currently subject to change at any time. You should not use this driver in production as it is still under development and is in no way supported by MongoDB Inc. We absolutely encourage you to experiment with it and provide us feedback on the API, design, and implementation. Bug reports and suggestions for improvements are welcomed, as are pull requests.

Note: This driver currently only supports MongoDB 3.0.x and 3.2.x. This driver is not expected to work with MongoDB 2.6 or any earlier versions. Do not use this driver if you need support for other versions of MongoDB.

Installation

Dependencies

Importing

The driver is available on crates.io. To use the MongoDB driver in your code, add the bson and mongodb packages to your Cargo.toml:

[dependencies]
mongodb = "0.3.11"

Alternately, you can use the MongoDB driver with SSL support. To do this, you must have OpenSSL installed on your system. Then, enable the ssl feature for MongoDB in your Cargo.toml:

[dependencies]
# ...
mongodb = { version = "0.3.11", features = ["ssl"] }

Then, import the bson and driver libraries within your code.

#[macro_use(bson, doc)]
extern crate mongodb;

or with Rust 2018:

extern crate mongodb;
use mongodb::{bson, doc};

Examples

Here's a basic example of driver usage:

use mongodb::{Bson, bson, doc};
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;

fn main() {
    let client = Client::connect("localhost", 27017)
        .expect("Failed to initialize standalone client.");

    let coll = client.db("test").collection("movies");

    let doc = doc! {
        "title": "Jaws",
        "array": [ 1, 2, 3 ],
    };

    // Insert document into 'test.movies' collection
    coll.insert_one(doc.clone(), None)
        .ok().expect("Failed to insert document.");

    // Find the document and receive a cursor
    let mut cursor = coll.find(Some(doc.clone()), None)
        .ok().expect("Failed to execute find.");

    let item = cursor.next();

    // cursor.next() returns an Option<Result<Document>>
    match item {
        Some(Ok(doc)) => match doc.get("title") {
            Some(&Bson::String(ref title)) => println!("{}", title),
            _ => panic!("Expected title to be a string!"),
        },
        Some(Err(_)) => panic!("Failed to get next from server!"),
        None => panic!("Server returned no results!"),
    }
}

To connect with SSL, use either ClientOptions::with_ssl or ClientOptions::with_unauthenticated_ssl and then Client::connect_with_options. Afterwards, the client can be used as above (note that the server will have to be configured to accept SSL connections and that you'll have to generate your own keys and certificates):

use mongodb::{Bson, bson, doc};
use mongodb::{Client, ClientOptions, ThreadedClient};
use mongodb::db::ThreadedDatabase;

fn main() {
    // Path to file containing trusted server certificates.
    let ca_file = "path/to/ca.crt";
    // Path to file containing client certificate.
    let certificate = "path/to/client.crt";
    // Path to file containing the client private key.
    let key_file = "path/to/client.key";
    // Whether or not to verify that the server certificate is valid. Unless you're just testing out something locally, this should ALWAYS be true.
    let verify_peer = true;

    let options = ClientOptions::with_ssl(ca_file, certificate, key_file, verify_peer);

    let client = Client::connect_with_options("localhost", 27017, options)
        .expect("Failed to initialize standalone client.");

    let coll = client.db("test").collection("movies");

    let doc = doc! {
        "title": "Jaws",
        "array": [ 1, 2, 3 ],
    };

    // Insert document into 'test.movies' collection
    coll.insert_one(doc.clone(), None)
        .ok().expect("Failed to insert document.");

    ...
}

Testing

The driver test suite is largely composed of integration tests and behavioral unit-tests, relying on the official MongoDB specifications repo.

The easiest way to thoroughly test the driver is to set your fork up with TravisCI. However, if you'd rather test the driver locally, you'll need to setup integration and specification tests.

NOTE: Each integration test uses a unique database/collection to allow tests to be parallelized, and will drop their dependencies before running. However, effects are not cleaned up afterwards.

Setting up integration tests

All integration tests run on the default MongoDB port, 27017. Before running the tests, ensure that a test database is setup to listen on that port.

If you don't have mongodb installed, download and install a version from the MongoDB Download Center. You can see a full list of versions being tested on Travis in the travis config.

After installation, run a MongoDB server on 27017:

mkdir -p ./data/test_db
mongod --dbpath ./data/test_db

Setting up the specifications submodule

Pull in the specifications submodule at tests/json/data/specs.

git submodule update --init

Running Tests

Run tests like a regular Rust program:

cargo test --verbose
Comments
  • bson library has released v0.2.0

    bson library has released v0.2.0

    I see the bson lib has released v0.2.0 and I can't use the latest versions of it or Serde without this mongo lib upgrading to the newest bson, I believe. Mongo is currently using bson 0.1.4.

    opened by freiguy1 19
  • Implement SSL

    Implement SSL

    Fixes #167.

    The most straightforward way to add SSL support to the driver was to use OpenSSL, so that's what I went with. This has the downside of not working on systems without OpenSSL installed, so in the interest of still allowing people on such systems to compile/use the driver, I added SSL as an optional feature. This adds a bit of complexity to the code in the form of needing [cfg(feature = "ssl")] in a lot of places, but I think this is preferable to users on systems without SSL installed by default (e.g. Windows) to still use the driver. I also elected to have the driver default to not including SSL support, and an informative error message is given if the user tries to connect with SSL without enabling it to ensure that nobody thinks that they're using SSL when they're actually not.

    opened by saghm 18
  • Failing to connect to a replica set with one member down.

    Failing to connect to a replica set with one member down.

    I'm seeing lock poison errors and panics when I'm trying to connect to a replica set of a sharded cluster that has a member down:

    thread '<unnamed>' panicked at 'rwlock read lock would result in deadlock', src/libstd/sys/unix/rwlock.rs:59
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    stack backtrace:
       0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
       1: std::panicking::default_hook::{{closure}}
       2: std::panicking::default_hook
       3: std::panicking::rust_panic_with_hook
       4: std::panicking::begin_panic
       5: std::sys::imp::rwlock::RWLock::read
       6: std::sys_common::rwlock::RWLock::read
       7: <std::sync::rwlock::RwLock<T>>::read
       8: mongodb::topology::TopologyDescription::check_if_has_primary
       9: mongodb::topology::TopologyDescription::update_private
      10: mongodb::topology::TopologyDescription::update
      11: mongodb::topology::monitor::Monitor::update_top_description
      12: mongodb::topology::monitor::Monitor::set_err
      13: mongodb::topology::monitor::Monitor::execute_update
      14: mongodb::topology::monitor::Monitor::run
      15: mongodb::topology::server::Server::new::{{closure}}
    thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "PoisonError { inner: .. }"', src/libcore/result.rs:859
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    stack backtrace:
       0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
       1: std::panicking::default_hook::{{closure}}
       2: std::panicking::default_hook
       3: std::panicking::rust_panic_with_hook
       4: std::panicking::begin_panic
       5: std::panicking::begin_panic_fmt
       6: rust_begin_unwind
       7: core::panicking::panic_fmt
       8: core::result::unwrap_failed
       9: <core::result::Result<T, E>>::unwrap
      10: mongodb::topology::monitor::Monitor::update_top_description
      11: mongodb::topology::monitor::Monitor::update_with_is_master_cursor
      12: mongodb::topology::monitor::Monitor::execute_update
      13: mongodb::topology::monitor::Monitor::run
      14: mongodb::topology::server::Server::new::{{closure}}
    thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "PoisonError { inner: .. }"', src/libcore/result.rs:859
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
    stack backtrace:
       0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
       1: std::panicking::default_hook::{{closure}}
       2: std::panicking::default_hook
       3: std::panicking::rust_panic_with_hook
       4: std::panicking::begin_panic
       5: std::panicking::begin_panic_fmt
       6: rust_begin_unwind
       7: core::panicking::panic_fmt
       8: core::result::unwrap_failed
       9: <core::result::Result<T, E>>::unwrap
      10: mongodb::topology::monitor::Monitor::update_top_description
      11: mongodb::topology::monitor::Monitor::update_with_is_master_cursor
      12: mongodb::topology::monitor::Monitor::execute_update
      13: mongodb::topology::monitor::Monitor::run
      14: mongodb::topology::server::Server::new::{{closure}}
    

    I've tried setting ReadMode::Primary as ReadPreference but still it panics.

    For context, I'm writing a tool to analyse the data from the profiling collections on each shard (for a specific database), so I get a list of all the shards from a mongos or the config servers and then connect to each shard from separate thread.

    In this particular case, one of the replica sets that consists of one arbiter, two healthy member and a third failed/unreachable member was giving me these errors which basically kills the whole thread for this shard. When I removed the faulty member I can connect again without problems.

    opened by ndenev 17
  • Multithreading support

    Multithreading support

    The first attempt at multithreading support was made in #87, but the solution of aliasing Arc types and then adding traits is rather messy. There should be a cleaner solution implemented at some point to avoid forcing users to import both the alias types and the bulky traits.

    opened by saghm 17
  • Grand cleanup

    Grand cleanup

    Hey there!

    First off, thanks for making a MongoDB driver for Rust!

    This PR cleans up and modernizes the code somewhat, improving its efficiency, interoperability, and style. In particular, the following modifications have been made. These, I believe, do not alter either the API or the modus operandi of the library.

    • Remove many unnecessary mutations, allocations and copies, especially around constructing BSON documents and default-able types, often via the struct update syntax (e.g. let mut foo = Foo::default(); foo.bar = baz; -> let foo = Foo { bar: baz, ..Foo::default() };
    • Replace complicated control flow around optionals and results with standard library methods
    • Rewrite several mutating raw for loops using Iterator methods
    • #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] or at least as many of them as possible and makes sense for several public-facing types.
    • Replace remaining uses of try!() with ?
    • Replace check-and-force with pattern matching, e.g. if vec.len() == 1 { &vec[0] } -> if let Some(…) = vec.get(0), or if opt.is_some() { opt.unwrap().do_stuff() } -> if let Some(val) = opt { val.do_stuff() }
    • Rewrite unneeded macro invocations using functions (e.g. vec![] -> Vec::new(), doc!{} -> Document::new())
    • Eliminate some closures using beta-reduction, e.g. map(|foo| foo.to_bson()) -> map(Foo::to_bson)
    • Simplify some unnecessarily complex code in general

    Furthermore, I have identified and marked with XXX a few potential issues regarding lock guards. I have not actually modified the corresponding code because I might be misunderstanding it, however I think it would be valuable to discuss this issue separately.

    opened by H2CO3 16
  • Project Status

    Project Status

    I would like to inquire about the mongo Rust driver project status, as it appears that development has stalled for some time, with multiple pull requests waiting to be merged.

    We have a pull request opened since March to address a serious issue that we found in production on our side: https://github.com/mongodb-labs/mongo-rust-driver-prototype/pull/304

    Somebody else apparently identified the same issue just two weeks ago, because it still isn't fixed on master: https://github.com/mongodb-labs/mongo-rust-driver-prototype/issues/335

    Issues with circular references causing leaks, and the lack of proper replica set support are becoming a serious issue for us. We use MongoDB in all of our Rust microservices, and we'd need to get things moving.

    I found in another pull request a comment regarding the development of a new, official MongoDB Rust driver, dating from September 18th: https://github.com/mongodb-labs/mongo-rust-driver-prototype/pull/302#issuecomment-532677869

    Can we expect a public release of this new driver anytime soon, and if not, can we at least get more of the pull requests with good fixes merged in master? This is becoming a critical issue for us, so we'll be investing time trying to fix issues, but it's all wasted if it remains on our own fork while waiting for a completely new Rust driver to come out.

    opened by awakecoding 14
  • Authentication succeeds while it shouldn't

    Authentication succeeds while it shouldn't

    I'm using something like this:

    let uri = "mongodb://user:pass@localhost:27017/coordinator";
    let client = Client::with_uri(uri)?;
    

    No error is reported, while when I run the same on command line it fails with "login failed". That's because this database has no authentication.

    Is this normal or should I use some different method to capture the connect error?

    opened by nkostoulas 14
  • Problems with Authentication

    Problems with Authentication

    Hi i am trying to connect to the Atlas MongoDB (using your latest changes branch with a way to do not pass CA)

    Code example:

    let mut options = ClientOptions::with_unauthenticated_ssl(None, false);
      options.read_preference = Some(ReadPreference::new(ReadMode::SecondaryPreferred, None));
    
      let client = Client::with_uri_and_options(
          "mongodb://cluster-shard-00-00:27017,cluster-shard-00-01:27017,cluster-shard-00-02:27017/test?replicaSet=Cluster-shard-0",
          options
        )
        .unwrap();
    
      let mut db = client.db("my_super_db");
      db.auth("user", "password").unwrap();
    

    how ever i am always getting this error:

     on an `Err` value: OperationError("Authentication failed.")'
    

    I have tried many different ways to change url and created different users a well how ever there is always two diffferent errors one is Authentication failed. and sometimes i get No servers available for the provided ReadPreference. second one only happens when i dont use with_unauthenticated_ssl.

    opened by goriunov 14
  • Some connection URIs are not supported

    Some connection URIs are not supported

    Connection URIs to MongoDB Atlas that start with mongodb+srv:// don't work, and even with mongodb://, supplying connection options there in the URI doesn't to work. My connection URI looks like this: mongodb://<USERNAME>:<PASSWORD>@<SECONDARY SERVER>,<PRIMARY SERVER>,<SECONDARY SERVER>/test?ssl=true&replicaSet=<SOME STUFF>&authSource=admin&retryWrites=true. This doesn't work, and I was told that I'm supposed to specify the connection options using ClientOptions, but I don't know how.

    opened by cubetastic33 14
  • how to work with update one

    how to work with update one

    Hello, I have three fields that either all, some or one of them can be updated. Idk know how to set it up in order to take this into account. Attached is what I have so far, but this does not work because need to have those $set keywords in there somewhere somehow.

    update_one

    opened by karasjoh000 13
  • Fixed the

    Fixed the "borrowing issue"

    Instead of Database having a reference to Client and Collection having a reference to Database, they now both use Arc's, which allows them to be used in multiple threads.

    PR LGTM 
    opened by saghm 13
Releases(0.3.3)
Owner
MongoDB, Inc. Labs
Experimental projects from MongoDB, Inc. (None of these projects is a supported MongoDB product)
MongoDB, Inc. Labs
Cassandra (CQL) driver for Rust, using the DataStax C/C++ driver under the covers.

cassandra-cpp This is a maintained Rust project that exposes the DataStax cpp driver at https://github.com/datastax/cpp-driver/ in a somewhat-sane cra

null 93 Jan 7, 2023
This is a maintained rust project that exposes the cpp driver at cpp-driver in a somewhat-sane crate.

cassandra-rs This is a maintained rust project that exposes the cpp driver at https://github.com/datastax/cpp-driver/ in a somewhat-sane crate. For th

Tupshin Harper 51 Aug 20, 2020
Official Skytable client driver for Rust

Skytable client Introduction This library is the official client for the free and open-source NoSQL database Skytable. First, go ahead and install Sky

Skytable 29 Nov 24, 2022
Blazingly fast data generation & seeding for MongoDB

Planter Blazingly fast and simple data generation & seeding for MongoDB Installation Use the package manager cargo to install planter. Add the followi

Valencian Digital 4 Jan 12, 2022
The most efficient, scalable, and fast production-ready serverless REST API backend which provides CRUD operations for a MongoDB collection

Optimal CRUD Mongo Goals of This Project This is meant to be the most efficient, scalable, and fast production-ready serverless REST API backend which

Evaluates2 1 Feb 22, 2022
Teach your PostgreSQL database how to speak MongoDB Wire Protocol

“If it looks like MongoDB, swims like MongoDB, and quacks like MongoDB, then it probably is PostgreSQL.” ?? Discord | Online Demo | Intro Video | Quic

Felipe Coury 261 Jun 18, 2023
Automatically publish MongoDB changes to Redis for Meteor.

changestream-to-redis Warning The project is currently in its alpha phase. There are no production loads using it yet nor any large-scale tests were c

Radosław Miernik 8 Jul 29, 2023
An ArangoDB driver for Rust

Rincon Rincon is an ArangoDB driver for Rust. It enables low level access to ArangoDB in a typesafe and Rust idiomatic manner. The name Rincon is deri

Innoave 35 Mar 21, 2021
TDS 7.2+ (mssql / Microsoft SQL Server) async driver for rust

Tiberius A native Microsoft SQL Server (TDS) client for Rust. Supported SQL Server versions Version Support level Notes 2019 Tested on CI 2017 Tested

Prisma 189 Dec 25, 2022
Asyncronous Rust Mysql driver based on Tokio.

mysql-async Tokio based asynchronous MySql client library for rust programming language. Installation Library hosted on crates.io. [dependencies] mysq

Anatoly I 292 Dec 30, 2022
Native PostgreSQL driver for the Rust programming language

Rust-Postgres PostgreSQL support for Rust. postgres Documentation A native, synchronous PostgreSQL client. tokio-postgres Documentation A native, asyn

Steven Fackler 2.8k Jan 8, 2023
cogo rust coroutine database driver (Mysql,Postgres,Sqlite)

cdbc Coroutine Database driver Connectivity.based on cogo High concurrency,based on coroutine No Future<'q,Output=*>,No async fn, No .await , no Poll*

co-rs 10 Nov 13, 2022
This is an Oracle database driver for Rust based on ODPI-C

Rust-oracle This is an Oracle database driver for Rust based on ODPI-C. Change Log See ChangeLog.md. Build-time Requirements C compiler. See Compile-t

Kubo Takehiro 138 Dec 23, 2022
Easy to use rust driver for arangoDB

arangors arangors is an intuitive rust client for ArangoDB, inspired by pyArango. arangors enables you to connect with ArangoDB server, access to data

fMeow 116 Jan 1, 2023
A Rust port of Pimoroni's uc8151 driver

uc8151-rs - a no-std Rust library for the UC8151(IL0373) e-ink display This is a Rust port of the Pimoroni UC8151 library. UC8151 is also sometimes re

null 6 Dec 15, 2022
ENC28J60 Linux network driver written in Rust.

enc28j60rs ENC28J60 Linux ethernet driver written in Rust. Tested with Raspberry Pi 4 Model B + Linux kernel 6.2.8 + Raspberry Pi OS AArch64. Kernel T

Ryo Munakata 11 May 1, 2023
MIPI Display Serial Interface unified driver

mipidsi This crate provides a generic display driver to connect to TFT displays that implement the MIPI DSI. Uses display_interface to talk to the har

Aleš Katona 31 Dec 20, 2022
TTVM Intermediate Representation driver

ttir - TTVM IR Driver ttir is driver for the TTVM IR located in ttvm. Usage Run the following command in your shell: cargo install ttir Features Easy

maDeveloper 1 Nov 2, 2021
e-paper/e-ink monitor linux driver

Ardoise: e-paper/e-ink monitor Goal: Create a e-paper/e-ink monitorfor linux. My personal use is a typewriter. Written in Rust Latency is 0,2s when th

Cyril Jacquet 1 Dec 8, 2022