NoSQL and friends
Recipe | Crates | Categories |
---|---|---|
Connect to MongoDB | ||
Connect to Redis |
Connect to MongoDB
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;
#[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();
// Example: mongodb://root:passwd@server:27017/
let mongo_uri = env::var("MONGO_URI")?;
let client = Client::with_uri_str(&mongo_uri).await?;
let db = client.database("test_db");
let collection = db.collection::<User>("users");
let user = User {
name: String::from("Alice"),
age: 30,
};
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-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;
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",
};
// The URL format is
// protocol=<protocol>]] For example, "redis://127.0.0.1/"
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()?)
}
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(())
}
cassandra_protocol
Cassandra protocol implementation in Rust. This crate provides a low-level implementation of the Cassandra protocol. It is used by the cdrs
crate to communicate with Cassandra.
cdrs_tokio
Async Cassandra DB driver written in Rust. This crate provides an asynchronous driver for Cassandra. It is built on top of the cdrs
crate and uses the tokio
runtime.
// // Async Cassandra DB driver written in Rust
// use std::sync::Arc;
// use cdrs_tokio::IntoCdrsValue;
// use cdrs_tokio::TryFromRow;
// use cdrs_tokio::TryFromUdt;
// use cdrs_tokio::authenticators::StaticPasswordAuthenticatorProvider;
// use cdrs_tokio::cluster::NodeTcpConfigBuilder;
// use cdrs_tokio::cluster::TcpConnectionManager;
// use cdrs_tokio::cluster::session::Session;
// use cdrs_tokio::cluster::session::SessionBuilder;
// use cdrs_tokio::cluster::session::TcpSessionBuilder;
// use cdrs_tokio::load_balancing::RoundRobinLoadBalancingStrategy;
// use cdrs_tokio::query::*;
// use cdrs_tokio::query_values;
// use cdrs_tokio::transport::TransportTcp;
// use tokio;
// use uuid::Uuid;
// // `cdrs` is a native Cassandra DB client written in Rust.
// type CurrentSession = Session<
// TransportTcp,
// TcpConnectionManager,
// RoundRobinLoadBalancingStrategy<TransportTcp, TcpConnectionManager>,
// >;
// #[derive(Clone, Debug, IntoCdrsValue, TryFromRow, PartialEq)]
// struct RowStruct {
// key: Uuid,
// name: String,
// age: u32,
// }
// impl RowStruct {
// fn into_query_values(self) -> QueryValues {
// // Transforms arguments to values consumed by queries
// query_values!("key" => self.key)
// }
// }
// #[tokio::main]
// async fn main() -> anyhow::Result<()> {
// let user = "user";
// let password = "password";
// let auth = StaticPasswordAuthenticatorProvider::new(&user, &password);
// // For tests, you may use
// // cdrs_tokio::authenticators::NoneAuthenticatorProvider
// // Connect to a Cassandra cluster
// let cluster_config = NodeTcpConfigBuilder::new()
// .with_contact_point("127.0.0.1:9042".into())
// .with_authenticator_provider(Arc::new(auth))
// .build()
// .await?;
// // Create a CDRS session that holds a pool of connections to nodes
// // and provides an interface for interacting with the cluster.
// let session: CurrentSession = TcpSessionBuilder::new(
// RoundRobinLoadBalancingStrategy::new(),
// cluster_config,
// )
// .build()
// .await?;
// // Create keyspace and table (if they don't exist)
// session
// .query(
// "CREATE KEYSPACE IF NOT EXISTS test_keyspace WITH replication =
// {'class': 'SimpleStrategy', 'replication_factor': 1};" )
// .await?;
// session
// .query(
// "CREATE TABLE IF NOT EXISTS test_keyspace.users (id UUID PRIMARY
// KEY, name TEXT, age INT);" )
// .await?;
// // Insert a row into the 'users' table
// let insert_query =
// "INSERT INTO test_keyspace.users (id, name, age) VALUES (?, ?, ?);";
// let id = Uuid::new_v4();
// let name = "Alice";
// let age = 30;
// let row = RowStruct {
// key: id,
// name: name.to_string(),
// age,
// };
// session
// .query_with_values(insert_query, row.into_query_values())
// .await?;
// println!("Inserted user: {} (ID: {})", name, id);
// // Query the inserted row
// let select_query =
// "SELECT id, name, age FROM test_keyspace.users WHERE name = ?;";
// let rows = session
// .query_with_values(select_query, (name,))
// .await?
// .response_body()?
// .into_rows()
// .ok_or_else(|| anyhow::anyhow!("No rows in the result set"))?;
// // Display the result of the query
// for row in rows {
// let (id, name, age): (Uuid, String, i32) = row.try_into()?;
// println!("Found user: {} (ID: {}, Age: {})", name, id, age);
// }
// Ok(())
// }