NoSQL and Friends

Connect to MongoDB

mongodb mongodb-crates.io mongodb-github mongodb-lib.rs cat-asynchronous cat-database cat-web-programming

This is the officially supported MongoDB Rust driver, a client side library that can be used to interact with MongoDB deployments in Rust applications. It uses the bson crate for BSON support. The driver contains a fully async API that requires tokio. The driver also has a sync API that may be enabled via feature flags.

use std::env;

use dotenvy::dotenv;
use mongodb::Client;
use mongodb::bson::doc;
use serde::Deserialize;
use serde::Serialize;

/// Represents a user with a name and age.
#[derive(Debug, Serialize, Deserialize)]
struct User {
    name: String,
    age: i32,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Read the .env file, if present.
    dotenv().ok();

    // Retrieve the MongoDB connection URI from the environment variable.
    // Example: mongodb://user:password@server:27017/
    let mongo_uri = env::var("MONGO_URI")?;
    // Create a new MongoDB client.
    let client = Client::with_uri_str(&mongo_uri).await?;
    // Get a handle to the "test_db" database.
    let db = client.database("test_db");
    // Get a handle to the "users" collection, expecting documents of type
    // `User`.
    let collection = db.collection::<User>("users");

    // Create a new user.
    let user = User {
        name: String::from("Alice"),
        age: 30,
    };
    // Insert the user into the collection.
    collection.insert_one(&user).await?;

    let filter = doc! { "name": "Alice" };
    if let Some(user) = collection.find_one(filter).await? {
        println!("Found user: {:?}", user);
    } else {
        println!("User not found");
    }

    Ok(())
}

Connect to Redis

redis redis-crates.io redis-github redis-lib.rs

Redis-rs is a high level redis library for Rust. It provides convenient access to all Redis functionality through a very flexible but low-level API. It uses a customizable type conversion trait so that any operation can return results in just the type you are expecting. This makes for a very pleasant development experience.

use std::env;

use anyhow::Context;
use anyhow::Result;
use redis::Commands;
use redis::Connection;

/// Establishes a connection to a Redis server.
///
/// This function reads environment variables to determine the Redis server's
/// hostname, password, and whether to use a secure connection (TLS). It then
/// constructs a connection URL and attempts to connect to the server.
///
/// # Returns
///
/// A `Result` containing a `Connection` to the Redis server on success, or an
/// error if the connection fails.
fn connect() -> Result<Connection> {
    let redis_host_name = env::var("REDIS_HOSTNAME")
        .context("missing environment variable REDIS_HOSTNAME")?;
    let redis_password = env::var("REDIS_PASSWORD").unwrap_or_default();
    // Does Redis server need a secure connection?
    let uri_scheme = match env::var("IS_TLS") {
        Ok(_) => "rediss",
        Err(_) => "redis",
    };
    let redis_conn_url =
        format!("{}://:{}@{}", uri_scheme, redis_password, redis_host_name);
    // `open` does not actually open a connection yet, but it does perform some
    // basic checks on the URL that might make the operation fail.
    Ok(redis::Client::open(redis_conn_url)?.get_connection()?)
}

/// Fetches an integer value from Redis.
///
/// This function connects to a Redis server, sets a key-value pair ("my_key",
/// 42), and then retrieves the value associated with "my_key".
///
/// # Returns
///
/// A `Result` containing the integer value retrieved from Redis on success, or
/// an error if the operation fails.
fn fetch_an_integer() -> Result<isize> {
    let mut con = connect()?;
    // Throw away the result, just make sure it does not fail.
    let _: () = con.set("my_key", 42)?;
    // Read back the key and return it. Because the return value
    // from the function is a result for integer, this will automatically
    // convert into one.
    Ok(con.get("my_key")?)
}

fn main() -> Result<()> {
    let my_int = fetch_an_integer()?;
    println!("{}", my_int);
    Ok(())
}

Connect to Cassandra Using cdrs_tokio

cdrs-tokio cdrs-tokio-crates.io cdrs-tokio-github cdrs-tokio-lib.rs cat-asynchronous cat-database

cdrs_tokio is an async Cassandra DB (or Scylla DB) driver. It uses the tokio async runtime.

// // COMING SOON

Connect to Cassandra Using cassandra_protocol

cassandra-protocol cassandra-protocol-crates.io cassandra-protocol-github cassandra-protocol-lib.rs cat-asynchronous cat-database

cassandra-protocol provides a Cassandra protocol implementation in Rust. Prefer the cdrs_tokio crate unless you need a low-level implementation.

// // COMING SOON