MongoDB rustの公式ドライバー（alpha版）を試す

# 概要

MongoDB rustの公式ドライバー（alpha版）がリリースされているようなので試してみました。
Rustの本は購入はしたものの積読状態だったのでインストールから始めて、RustでMongoDBドライバーを試すのに必要な所だけ半日ほど勉強しました。そんなこんなで試行錯誤しながら記事を書いてますから変なところがあると思います。これを機に本格的にRustの勉強をしようと思っています。

# 環境

- Windows 10
- MongoDB Community版 4.2.2
- rust 1.40.0
- MongoDB rust
    - ドライバー 0.9.0 (alpha版)
        - https://crates.io/crates/mongodb
        - https://github.com/mongodb/mongo-rust-driver
    - bson   0.14.0
        - https://crates.io/crates/bson
        - https://github.com/mongodb/bson-rust

# 実装

## Cargo.tomlのdependenciesへの追加

```toml:Cargo.toml
[dependencies]

mongodb ="0.9.0"
bson = "0.14.0"
```

## ドキュメントに載っているコードを試す


```rust:main.rs
use mongodb::{error::Result, options::{ClientOptions, FindOptions}, Client};
use bson::{doc, bson, Bson};

fn main() {
    let client = connect_mongo().expect("failed to connect");
    list_db(&client).expect("failed to list db names");
    list_collection(&client, "test").expect("failed to list collection names");
    insert_docs(&client).expect("failed to insert docs");
    find_docs(&client).expect("failed to find docs");
}

fn connect_mongo() -> Result<Client> {
    // Parse a connection string into an options struct.
    let mut client_options = ClientOptions::parse("mongodb://localhost:27017")?;

    // 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)?;
    Ok(client)
}

fn list_db(client: &Client) -> Result<()> {
    // List the names of the databases in that deployment.
    println!("------ print db --------");
    for db_name in client.list_database_names(None)? {
        println!("{}", db_name);
    }
    Ok(())
}

fn list_collection(client: &Client, dbname: &str) -> Result<()> {
    // Get a handle to a database.
    let db = client.database(dbname);

    // List the names of the collections in that database.
    println!("------ print collection ({}) --------", dbname);
    for collection_name in db.list_collection_names(None)? {
        println!("{}", collection_name);
    }
    Ok(())
}

fn insert_docs(client: &Client) -> Result<()> {
    // Get a handle to a collection in the database.
    let collection = client.database("test").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 "test.books" collection.
    collection.insert_many(docs, None)?;

    Ok(())
}

fn find_docs(client: &Client) -> Result<()> {
    // Get a handle to a collection in the database.
    let collection = client.database("test").collection("books");
    // 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 cursor = collection.find(filter, find_options)?;

    println!("------ print find  --------");
    // Iterate over the results of the cursor.
    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()),
        }
    }

    Ok(())
}
```

```
> cargo run
     Running `target\debug\mongorust.exe`
------ print db --------
admin
config
local
test
------ print collection (test) --------
col
system.profile
books
col2
------ print find  --------
title: 1984
title: Animal Farm
```


# 最後に


コードをコピペすればすぐに動作すると思ったが、`?演算子`と`Result`の使い方と`client変数の所有権`について良く分からず時間が掛かってしまった。　データを構造体で扱う例がなかったので今後調べてみます。

# リンク

[MongoDB rustの公式ドライバー（alpha版）を試す（２）（構造体を使う)](https://qiita.com/h6591/items/b1f938ed0c976aba3315)