🐥 การเชื่อมต่อและใช้งาน MongoDB ในภาษา Rust

การเชื่อมต่อและใช้งาน MongoDB ในภาษา Rust สามารถทำได้โดยใช้ไลบรารีทางการที่ชื่อว่า mongodb ร่วมกับ tokio สำหรับจัดการการทำงานแบบ Asynchronous และ serde สำหรับแปลงข้อมูล Struct เป็น BSON 1, 2

ตัวอย่างพื้นฐานตั้งแต่การตั้งค่าโปรเจกต์ไปจนถึงการจัดการข้อมูล (CRUD) ครบจบในไฟล์เดียวมีขั้นตอนดังนี้ครับ

  1. ตั้งค่า Dependencies ใน Cargo.toml

สร้างโปรเจกต์ใหม่ด้วยคำสั่ง cargo new rust-mongo-demo จากนั้นเพิ่มไลบรารีที่จำเป็นลงในไฟล์ Cargo.toml (อ้างอิงเวอร์ชันล่าสุดในตระกูล v3.x) 1, 2, 3

[dependencies]
mongodb = "3.9"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
futures = "0.3"
  1. ตัวอย่างโค้ด CRUD พื้นฐาน (src/main.rs)

ตัวอย่างนี้แสดงการเชื่อมต่อฐานข้อมูล การเพิ่ม (Insert) การค้นหา (Find) การอัปเดต (Update) และการลบข้อมูล (Delete) โดยใช้ Struct ของ Rust เพื่อให้ได้ความปลอดภัยของชนิดข้อมูล (Type-safe)

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

// กำหนดโครงสร้างข้อมูล (Model)
#[derive(Debug, Serialize, Deserialize)]
struct Book {
    #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
    id: Option<ObjectId>,
    title: String,
    author: String,
    year: i32,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    // 1. เชื่อมต่อกับ MongoDB (เปลี่ยน URI เป็นของคุณ เช่น MongoDB Atlas หรือ Localhost)
    let uri = "mongodb://localhost:27017";
    let client = Client::with_uri_str(uri).await?;

    // เลือก Database และ Collection (ระบุ Type เป็น Book)
    let db = client.database("library_db");
    let books_coll: Collection<Book> = db.collection("books");

    println!("เชื่อมต่อ MongoDB สำเร็จ!");

    // ---------------------------------------------------------
    // 2. CREATE: เพิ่มข้อมูลใหม่ (Insert One)
    // ---------------------------------------------------------
    let new_book = Book {
        id: None, // ให้ MongoDB สร้าง _id ให้อัตโนมัติ
        title: String::from("The Rust Programming Language"),
        author: String::from("Steve Klabnik"),
        year: 2023,
    };

    let insert_result = books_coll.insert_one(&new_book).await?;
    println!("เพิ่มข้อมูลสำเร็จ ID: {:?}", insert_result.inserted_id);

    // ---------------------------------------------------------
    // 3. READ: ค้นหาข้อมูล (Find One & Find Many)
    // ---------------------------------------------------------
    // ค้นหา 1 รายการ
    let filter = doc! { "title": "The Rust Programming Language" };
    if let Some(book) = books_coll.find_one(filter).await? {
        println!("พบหนังสือ: {:?}", book);
    }

    // ค้นหาหลายรายการ (ใช้ Cursor ร่วมกับ TryStreamExt)
    let mut cursor = books_coll.find(doc! {}).await?;
    println!("รายการหนังสือทั้งหมด:");
    while let Some(book) = cursor.try_next().await? {
        println!("- {} โดย {}", book.title, book.author);
    }

    // ---------------------------------------------------------
    // 4. UPDATE: แก้ไขข้อมูล (Update One)
    // ---------------------------------------------------------
    let update_filter = doc! { "title": "The Rust Programming Language" };
    let update_doc = doc! { "$set": { "year": 2025 } };

    let update_result = books_coll.update_one(update_filter, update_doc).await?;
    println!("อัปเดตข้อมูลแล้ว {} รายการ", update_result.modified_count);

    // ---------------------------------------------------------
    // 5. DELETE: ลบข้อมูล (Delete One)
    // ---------------------------------------------------------
    let delete_filter = doc! { "title": "The Rust Programming Language" };
    let delete_result = books_coll.delete_one(delete_filter).await?;
    println!("ลบข้อมูลแล้ว {} รายการ", delete_result.deleted_count);

    Ok(())
}

จุดสำคัญที่ควรรู้

หากต้องการต่อยอด ผมสามารถช่วยเขียนตัวอย่างเพิ่มเติมได้ครับ เพียงแจ้งว่าคุณสนใจส่วนไหนเป็นพิเศษ:
• การนำไปใช้ร่วมกับ Web Framework (เช่น Axum หรือ Actix-web) เพื่อสร้าง REST API
• การทำ Aggregation Pipeline หรือ Transactions
• การตั้งค่า Connection Pool และจัดการ Error สำหรับใช้งานจริงบน Production