Trabajo con bases de datos en Rust: PostgreSQL y MongoDB para principiantes
\n\nRust es un lenguaje de programación de sistemas moderno que está ganando popularidad gracias a su rendimiento y seguridad. Pero, ¿cómo trabajar con bases de datos en Rust? En este artículo analizaremos la conexión y ejecución de operaciones básicas con dos SGBD populares: PostgreSQL relacional y MongoDB orientada a documentos. El material está dirigido a desarrolladores principiantes familiarizados con los fundamentos de Rust.
\n\n¿Por qué Rust y las bases de datos son una buena combinación?
\n\nRust ofrece un sistema de tipos estricto y garantías de seguridad de memoria, lo que es especialmente valioso al trabajar con datos. Los errores de acceso a memoria, típicos de C/C++, se eliminan en tiempo de compilación. Además, el ecosistema de Rust incluye bibliotecas maduras para la interacción con bases de datos: diesel para PostgreSQL y el controlador oficial para MongoDB.
En este artículo aprenderemos a:
\n- \n
- Conectarnos a PostgreSQL y MongoDB desde Rust \n
- Realizar operaciones CRUD (crear, leer, actualizar, eliminar) \n
- Trabajar con los resultados de las consultas de forma segura y eficiente \n
1. Trabajo con PostgreSQL mediante la biblioteca Diesel
\n\nDiesel es un ORM y query builder para Rust que garantiza la seguridad de tipos en tiempo de compilación. Para empezar, agregue las dependencias en 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\nConfiguración de la conexión
\n\nCree un archivo .env con la URL de su base de datos:
DATABASE_URL=postgres://usuario:contraseña@localhost/mibd\n\nAhora escribamos el código para la conexión y creación de una tabla:
\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\nDefinición del esquema y modelo
\n\nCreemos la tabla users y el modelo correspondiente en 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\nOperaciones CRUD
\n\nEjemplo de creación y lectura de usuarios:
\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\nComo puede ver, Diesel verifica los tipos y nombres de las columnas en tiempo de compilación. Un error en el nombre del campo provocará un error de compilación, no un fallo en tiempo de ejecución.
\n\n2. Trabajo con MongoDB mediante el controlador oficial
\n\nMongoDB es una base de datos NoSQL que almacena datos en formato JSON-like