日本の山岳一覧・百名山 API を開発しましたCLICK !

Rust | MongoDBのドキュメントを検索する – find / find_one

Rust x MogoDB
  • URLをコピーしました!

Rust の MongoDB ドライバーである mongodb を使って、ドキュメント検索処理を実装します。

MongoDBのコレクションにドキュメントを検索する

  1. find:指定されたクエリ条件を満たすドキュメントを取得する
  2. find_one:指定されたクエリ条件を満たすドキュメントを”1つ”を取得する
目次

MongoDB のドキュメント検索

MongoDB の設定

今回は以下のデータベースとコネクションを作成した前提で実装します。

  • データベース:sample_db
  • コレクション:users

Cargo.toml

mongodb クレートを使います。

[dependencies]
tokio = "1.20.0"
serde = { version = "1.0", features = ["derive"] }
futures = "0.3.21"

[dependencies.mongodb]
version = "2.2.2"
default-features = false
features = ["tokio-runtime"]

find

find で指定されたクエリ条件を満たすドキュメントを取得します。

文字列の完全一致

nameの完全一致で検索かけ、ドキュメントを取得します。

use mongodb::{Client};
use mongodb::bson::doc;
use mongodb::bson::oid::ObjectId;
use serde::{Deserialize, Serialize};
use futures::stream::TryStreamExt;

#[derive(Deserialize, Serialize)]
struct User {
    #[serde(rename = "_id", skip_serializing)]
    id: Option<ObjectId>,
    name: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let client = Client::with_uri_str("your connection url strings").await?;
    let db = client.database("sample_db");
    let collection = db.collection::<User>("users");

    let filter = doc! {"name": "Ervin Howell"};
    let mut result = collection.find(filter, None).await?;

    while let Some(user) = result.try_next().await? {
        if let Some(id) = user.id {
            println!("id: {}, name: {}", id, user.name);
        }
    }

    Ok(())
}

文字列の部分一致

namelまたはLを含むという条件で検索かけ、ドキュメントを取得します。

use mongodb::{Client};
use mongodb::bson::doc;
use mongodb::bson::oid::ObjectId;
use serde::{Deserialize, Serialize};
use futures::stream::TryStreamExt;

#[derive(Deserialize, Serialize)]
struct User {
    #[serde(rename = "_id", skip_serializing)]
    id: Option<ObjectId>,
    name: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let client = Client::with_uri_str("your connection url strings").await?;
    let db = client.database("sample_db");
    let collection = db.collection::<User>("users");

    let filter = doc! {"name": {"$regex": "l", "$options": "i"}};
    let mut result = collection.find(filter, None).await?;

    while let Some(user) = result.try_next().await? {
        if let Some(id) = user.id {
            println!("id: {}, name: {}", id, user.name);
        }
    }

    Ok(())
}

FindOptions でオプションを指定する

FindOptions で並び順を指定することが可能です。

nameの降順を指定してみます。

use futures::stream::TryStreamExt;
use mongodb::bson::doc;
use mongodb::bson::oid::ObjectId;
use mongodb::options::FindOptions;
use mongodb::Client;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct User {
    #[serde(rename = "_id", skip_serializing)]
    id: Option<ObjectId>,
    name: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let client = Client::with_uri_str("your connection url strings").await?;
    let db = client.database("sample_db");
    let collection = db.collection::<User>("users");

    let filter = doc! {"name": {"$regex": "l", "$options": "i"}};
    let find_options = FindOptions::builder().sort(doc! {"name": -1}).build();
    let mut result = collection.find(filter, find_options).await?;

    while let Some(user) = result.try_next().await? {
        if let Some(id) = user.id {
            println!("id: {}, name: {}", id, user.name);
        }
    }

    Ok(())
}

find_one

find_one で指定されたクエリ条件を満たす文書を1つを取得します。

複数のドキュメントがクエリを満たす場合、ドキュメントの順序を反映した自然順序にしたがって最初のドキュメントを取得することができます。

use mongodb::bson::doc;
use mongodb::bson::oid::ObjectId;
use mongodb::Client;
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct User {
    #[serde(rename = "_id", skip_serializing)]
    id: Option<ObjectId>,
    name: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let client = Client::with_uri_str("your connection url strings").await?;
    let db = client.database("sample_db");
    let collection = db.collection::<User>("users");

    let filter = doc! {"name": {"$regex": "l", "$options": "i"}};
    let result = collection.find_one(filter, None).await?;

    if let Some(user) = result {
        if let Some(id) = user.id {
            println!("id: {}, name: {}", id, user.name);
        }
    }

    Ok(())
}

FindOneOptions でオプションを指定する

FindOneOptions で並び順を指定することが可能です。

nameの降順を指定するとドキュメントの順序が変わるので、取得結果が変わります。

use mongodb::{Client};
use mongodb::bson::doc;
use mongodb::bson::oid::ObjectId;
use serde::{Deserialize, Serialize};
use mongodb::options::FindOneOptions;

#[derive(Deserialize, Serialize)]
struct User {
    #[serde(rename = "_id", skip_serializing)]
    id: Option<ObjectId>,
    name: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let client = Client::with_uri_str("your connection url strings").await?;
    let db = client.database("sample_db");
    let collection = db.collection::<User>("users");

    let filter = doc! {"name": {"$regex": "l", "$options": "i"}};
    let find_one_options = FindOneOptions::builder().sort(doc! {"name": -1}).build();
    let result = collection.find_one(filter, find_one_options).await?;

    if let Some(user) = result {
        if let Some(id) = user.id {
            println!("id: {}, name: {}", id, user.name);
        }
    }

    Ok(())
}

まとめ

RDS でいうところSELECT * FROM users WHERE name = 'xxx'SELECT * FROM users WHERE name = 'xxx' LIMIT 1を実装することができました。

SQLに慣れたエンジニアでもとっつきなと感じました!

Rust x MogoDB

この記事が気に入ったら
フォローしてね!

  • URLをコピーしました!

コメント

コメントする

目次