العمل مع قواعد البيانات في Rust: PostgreSQL و MongoDB للمبتدئين
\n\nRust هي لغة برمجة نظامية حديثة تكتسب شعبية بفضل أدائها وأمانها. ولكن كيف تعمل مع قواعد البيانات في Rust؟ في هذه المقالة، سنشرح الاتصال وتنفيذ العمليات الأساسية مع نظامين شائعين لإدارة قواعد البيانات: PostgreSQL العلائقية و MongoDB الموجهة للمستندات. المادة موجهة للمطورين المبتدئين الذين لديهم معرفة أساسية بـ Rust.
\n\nلماذا يعتبر Rust وقواعد البيانات مزيجًا جيدًا؟
\n\nيقدم Rust نظامًا صارمًا للأنواع وضمانات أمان الذاكرة، وهو أمر قيم بشكل خاص عند العمل مع البيانات. يتم استبعاد أخطاء الوصول إلى الذاكرة، الشائعة في C/C++، في مرحلة التجميع. بالإضافة إلى ذلك، تتضمن بيئة Rust مكتبات ناضجة للتفاعل مع قواعد البيانات: diesel لـ PostgreSQL والسائق الرسمي لـ MongoDB.
في هذه المقالة، سنتعلم:
\n- \n
- الاتصال بـ PostgreSQL و MongoDB من Rust \n
- تنفيذ عمليات CRUD (إنشاء، قراءة، تحديث، حذف) \n
- العمل مع نتائج الاستعلامات بأمان وكفاءة \n
1. العمل مع PostgreSQL عبر مكتبة Diesel
\n\nDiesel هي ORM ومنشئ استعلامات لـ Rust، توفر أمان الأنواع على مستوى التجميع. للبدء، أضف التبعيات في Cargo.toml:
[dependencies]\ndiesel = { version = "2.1", features = ["postgres"] }\ndotenvy = "0.15"\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\ntokio = { version = "1.0", features = ["full"] }\n\nإعداد الاتصال
\n\nأنشئ ملف .env مع رابط قاعدة البيانات الخاصة بك:
DATABASE_URL=postgres://user:password@localhost/mydb\n\nالآن لنكتب الكود للاتصال وإنشاء جدول:
\n\nuse diesel::prelude::*;\nuse diesel::pg::PgConnection;\nuse dotenvy::dotenv;\nuse std::env;\n\npub fn establish_connection() -> PgConnection {\n dotenv().ok();\n let database_url = env::var("DATABASE_URL")\n .expect("DATABASE_URL must be set");\n PgConnection::establish(&database_url)\n .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))\n}\n\nتعريف المخطط والنموذج
\n\nلننشئ جدول users والنموذج المقابل في Rust:
// schema.rs\ntable! {\n users (id) {\n id -> Int4,\n name -> Varchar,\n email -> Varchar,\n created_at -> Timestamp,\n }\n}\n\n// models.rs\n#[derive(Queryable, Selectable)]\n#[diesel(table_name = crate::schema::users)]\n#[diesel(check_for_backend(diesel::pg::Pg))]\npub struct User {\n pub id: i32,\n pub name: String,\n pub email: String,\n pub created_at: chrono::NaiveDateTime,\n}\n\n#[derive(Insertable)]\n#[diesel(table_name = crate::schema::users)]\npub struct NewUser {\n pub name: String,\n pub email: String,\n}\n\nعمليات CRUD
\n\nمثال على إنشاء وقراءة المستخدمين:
\n\nuse crate::models::{User, NewUser};\nuse crate::schema::users;\n\npub fn create_user(conn: &mut PgConnection, name: &str, email: &str) -> User {\n let new_user = NewUser {\n name: name.to_string(),\n email: email.to_string(),\n };\n\n diesel::insert_into(users::table)\n .values(&new_user)\n .returning(User::as_returning())\n .get_result(conn)\n .expect("Error saving new user")\n}\n\npub fn get_all_users(conn: &mut PgConnection) -> Vec {\n users::table\n .load::(conn)\n .expect("Error loading users")\n} \n\nكما ترى، يتحقق Diesel من الأنواع وأسماء الأعمدة في مرحلة التجميع. سيؤدي الخطأ في اسم الحقل إلى خطأ في التجميع، وليس إلى فشل في وقت التشغيل.
\n\n2. العمل مع MongoDB عبر السائق الرسمي
\n\nMongoDB هي قاعدة بيانات NoSQL تخزن البيانات بتنسيق مشابه لـ JSON