Introducción: Por qué Rust y las bases de datos son una pareja ideal
Rust es un lenguaje de programación de sistemas moderno que está ganando cada vez más popularidad gracias a su rendimiento, seguridad de memoria y abstracciones de costo cero. Muchos desarrolladores que vienen del mundo de Python, JavaScript o Go se preguntan: ¿cómo trabajar con bases de datos en Rust? La respuesta es simple: Rust proporciona controladores potentes y seguros para trabajar tanto con bases de datos relacionales (PostgreSQL) como con bases de datos orientadas a documentos (MongoDB).
En este artículo analizaremos los fundamentos del trabajo con PostgreSQL y MongoDB en Rust. Aprenderá cómo configurar un proyecto, conectarse a bases de datos y realizar operaciones CRUD básicas. El artículo está orientado a principiantes, por lo que utilizaremos ejemplos simples y fáciles de entender.
1. Configuración del proyecto e instalación de dependencias
Antes de comenzar, asegúrese de tener instalados Rust y Cargo. Cree un nuevo proyecto:
cargo new rust_db_examplecd rust_db_exampleAbra el archivo Cargo.toml y agregue las dependencias necesarias. Para trabajar con PostgreSQL usaremos el crate tokio-postgres (controlador asíncrono) y serde para la serialización de datos. Para MongoDB, el controlador oficial mongodb.
[dependencies]tokio = { version = "1", features = ["full"] }tokio-postgres = "0.7"serde = { version = "1", features = ["derive"] }serde_json = "1"mongodb = "2.8"Tenga en cuenta: usamos tokio como runtime asíncrono, ya que ambos controladores funcionan de forma asíncrona. Esta es una práctica estándar para aplicaciones Rust modernas.
2. Trabajo con PostgreSQL en Rust
PostgreSQL es una potente base de datos relacional. Para trabajar con ella en Rust usaremos el crate tokio-postgres. Proporciona una interfaz asíncrona para ejecutar consultas SQL.
2.1 Conexión a la base de datos
Creemos una función para conectarnos a una base de datos PostgreSQL local. Asegúrese de tener el servidor PostgreSQL en ejecución y una base de datos creada (por ejemplo, test_db):
use tokio_postgres::{NoTls, Error};
#[tokio::main]async fn main() -> Result<(), Error> { // Cadena de conexión: postgresql://user:password@localhost/dbname let (client, connection) = tokio_postgres::connect( "host=localhost user=postgres dbname=test_db", NoTls, ).await?;
// Ejecutamos la conexión en segundo plano tokio::spawn(async move { if let Err(e) = connection.await { eprintln!("Error de conexión: {}", e); } });
println!("¡Conexión a PostgreSQL establecida!"); Ok(())}2.2 Creación de tabla e inserción de datos
Ahora creemos la tabla users e insertemos algunos registros:
// Creamos la tablaclient .execute( "CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(150) UNIQUE NOT NULL )", &[], ) .await?;
// Insertamos datoslet name = "Alice";let email = "alice@example.com";client .execute( "INSERT INTO users (name, email) VALUES ($1, $2)", &[&name, &email], ) .await?;
println!("¡Usuario {} agregado!", name);2.3 Lectura y actualización de datos
Ejecutemos una consulta SELECT y actualicemos un registro:
// Lectura de datoslet rows = client .query("SELECT id, name, email FROM users", &[]) .await?;
for row in rows { let id: i32 = row.get(0); let name: &str = row.get(1); let email: &str = row.get(2); println!("ID: {}, Nombre: {}, Email: {}", id, name, email);}
// Actualización de registroclient .execute( "UPDATE users SET email = $1 WHERE name = $2", &[&"alice_new