Rust の MongoDB ドライバーである mongodb を使って、ドキュメント検索処理を実装します。
MongoDBのコレクションにドキュメントを検索する
- find:指定されたクエリ条件を満たすドキュメントを取得する
- 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(())
}
文字列の部分一致
name
にl
または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に慣れたエンジニアでもとっつきなと感じました!
コメント