diff --git a/content/develop/data-types/strings.md b/content/develop/data-types/strings.md index 26cf1a54b..2814b772e 100644 --- a/content/develop/data-types/strings.md +++ b/content/develop/data-types/strings.md @@ -76,7 +76,7 @@ the [`MSET`]({{< relref "/commands/mset" >}}) and [`MGET`]({{< relref "/commands When [`MGET`]({{< relref "/commands/mget" >}}) is used, Redis returns an array of values. -### Strings as counters +## Strings as counters Even if strings are the basic values of Redis, there are interesting operations you can perform with them. For instance, one is atomic increment: diff --git a/local_examples/rust-async/dt-hash.rs b/local_examples/rust-async/dt-hash.rs new file mode 100644 index 000000000..0ed0dc981 --- /dev/null +++ b/local_examples/rust-async/dt-hash.rs @@ -0,0 +1,203 @@ +// EXAMPLE: hash_tutorial +#[cfg(test)] +mod tests { + use redis::AsyncCommands; + + #[tokio::test] + async fn run() { + let mut r = match redis::Client::open("redis://127.0.0.1") { + Ok(client) => { + match client.get_multiplexed_async_connection().await { + Ok(conn) => conn, + Err(e) => { + println!("Failed to connect to Redis: {e}"); + return; + } + } + }, + Err(e) => { + println!("Failed to create Redis client: {e}"); + return; + } + }; + // REMOVE_START + let _: () = r.flushall().await.expect("Failed to flushall"); + // REMOVE_END + + // STEP_START set_get_all + let hash_fields = [ + ("model", "Deimos"), + ("brand", "Ergonom"), + ("type", "Enduro bikes"), + ("price", "4972"), + ]; + + if let Ok(res) = r.hset_multiple("bike:1", &hash_fields).await { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.hget("bike:1", "model").await { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> Deimos + // REMOVE_START + assert_eq!(res, "Deimos"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1 model: {e}"); + return; + } + }; + + match r.hget("bike:1", "price").await { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> 4972 + // REMOVE_START + assert_eq!(res, "4972"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1 price: {e}"); + return; + } + }; + + match r.hgetall("bike:1").await { + Ok(res) => { + let res: Vec<(String, String)> = res; + println!("{res:?}"); + // >>> [("model", "Deimos"), ("brand", "Ergonom"), ("type", "Enduro bikes"), ("price", "4972")] + // REMOVE_START + assert_eq!(res.len(), 4); + assert_eq!(res[0].0, "model"); + assert_eq!(res[0].1, "Deimos"); + assert_eq!(res[1].0, "brand"); + assert_eq!(res[1].1, "Ergonom"); + assert_eq!(res[2].0, "type"); + assert_eq!(res[2].1, "Enduro bikes"); + assert_eq!(res[3].0, "price"); + assert_eq!(res[3].1, "4972"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + // STEP_END + + // STEP_START hmget + match r.hmget("bike:1", &["model", "price"]).await { + Ok(res) => { + let res: Vec = res; + println!("{res:?}"); // >>> ["Deimos", "4972"] + // REMOVE_START + assert_eq!(res.len(), 2); + assert_eq!(res[0], "Deimos"); + assert_eq!(res[1], "4972"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + // STEP_END + + // STEP_START hincrby + if let Ok(res) = r.hincr("bike:1", "price", 100).await { + let res: i32 = res; + println!("{res}"); // >>> 5072 + // REMOVE_START + assert_eq!(res, 5072); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1", "price", -100).await { + let res: i32 = res; + println!("{res}"); // >>> 4972 + // REMOVE_START + assert_eq!(res, 4972); + // REMOVE_END + } + // STEP_END + + // STEP_START incrby_get_mget + if let Ok(res) = r.hincr("bike:1:stats", "rides", 1).await { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "rides", 1).await { + let res: i32 = res; + println!("{res}"); // >>> 2 + // REMOVE_START + assert_eq!(res, 2); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "rides", 1).await { + let res: i32 = res; + println!("{res}"); // >>> 3 + // REMOVE_START + assert_eq!(res, 3); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "crashes", 1).await { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "owners", 1).await { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + match r.hget("bike:1:stats", "rides").await { + Ok(res) => { + let res: i32 = res; + println!("{res}"); // >>> 3 + // REMOVE_START + assert_eq!(res, 3); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1:stats rides: {e}"); + return; + } + }; + + match r.hmget("bike:1:stats", &["crashes", "owners"]).await { + Ok(res) => { + let res: Vec = res; + println!("{res:?}"); // >>> [1, 1] + // REMOVE_START + assert_eq!(res.len(), 2); + assert_eq!(res[0], 1); + assert_eq!(res[1], 1); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1:stats crashes and owners: {e}"); + return; + } + }; + // STEP_END + } +} \ No newline at end of file diff --git a/local_examples/rust-async/dt-string.rs b/local_examples/rust-async/dt-string.rs new file mode 100644 index 000000000..1626e19e4 --- /dev/null +++ b/local_examples/rust-async/dt-string.rs @@ -0,0 +1,148 @@ + +// EXAMPLE: set_tutorial +#[cfg(test)] +mod tests { + use redis::{AsyncCommands, ExistenceCheck}; + + #[tokio::test] + async fn run() { + let mut r = match redis::Client::open("redis://127.0.0.1") { + Ok(client) => { + match client.get_multiplexed_async_connection().await { + Ok(conn) => conn, + Err(e) => { + println!("Failed to connect to Redis: {e}"); + return; + } + } + }, + Err(e) => { + println!("Failed to create Redis client: {e}"); + return; + } + }; + + // STEP_START set_get + if let Ok(res) = r.set("bike:1", "Deimos").await { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.get("bike:1").await { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> Deimos + // REMOVE_START + assert_eq!(res, "Deimos"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting foo: {e}"); + return; + } + }; + // STEP_END + + // STEP_START setnx_xx + if let Ok(res) = r.set_options("bike:1", "bike", redis::SetOptions::default().conditional_set(ExistenceCheck::NX)).await { + let res: bool = res; + println!("{res}"); // >>> false + // REMOVE_START + assert!(!res); + // REMOVE_END + } + + match r.get("bike:1").await { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> Deimos + // REMOVE_START + assert_eq!(res, "Deimos"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting foo: {e}"); + return; + } + }; + + if let Ok(res) = r.set_options("bike:1", "bike", redis::SetOptions::default().conditional_set(ExistenceCheck::XX)).await { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.get("bike:1").await { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> bike + // REMOVE_START + assert_eq!(res, "bike"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting foo: {e}"); + return; + } + }; + // STEP_END + + // STEP_START mset + if let Ok(res) = r.mset(&[("bike:1", "Deimos"), ("bike:2", "Ares"), ("bike:3", "Vanth")]).await { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.mget(&["bike:1", "bike:2", "bike:3"]).await { + Ok(res) => { + let res: Vec = res; + println!("{res:?}"); // >>> ["Deimos", "Ares", "Vanth"] + // REMOVE_START + assert_eq!(res.len(), 3); + assert_eq!(res[0], "Deimos"); + assert_eq!(res[1], "Ares"); + assert_eq!(res[2], "Vanth"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting foo: {e}"); + return; + } + }; + // STEP_END + + // STEP_START incr + if let Ok(res) = r.set("total_crashes", 0).await { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + if let Ok(res) = r.incr("total_crashes", 1).await { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + if let Ok(res) = r.incr("total_crashes", 10).await { + let res: i32 = res; + println!("{res}"); // >>> 11 + // REMOVE_START + assert_eq!(res, 11); + // REMOVE_END + } + // STEP_END + } +} \ No newline at end of file diff --git a/local_examples/rust-sync/dt-hash.rs b/local_examples/rust-sync/dt-hash.rs new file mode 100644 index 000000000..a052b6725 --- /dev/null +++ b/local_examples/rust-sync/dt-hash.rs @@ -0,0 +1,203 @@ +// EXAMPLE: hash_tutorial +#[cfg(test)] +mod hash_tests { + use redis::Commands; + + #[test] + fn run() { + let mut r = match redis::Client::open("redis://127.0.0.1") { + Ok(client) => { + match client.get_connection() { + Ok(conn) => conn, + Err(e) => { + println!("Failed to connect to Redis: {e}"); + return; + } + } + }, + Err(e) => { + println!("Failed to create Redis client: {e}"); + return; + } + }; + // REMOVE_START + let _: () = r.flushall().expect("Failed to flushall"); + // REMOVE_END + + // STEP_START set_get_all + let hash_fields = [ + ("model", "Deimos"), + ("brand", "Ergonom"), + ("type", "Enduro bikes"), + ("price", "4972"), + ]; + + if let Ok(res) = r.hset_multiple("bike:1", &hash_fields) { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.hget("bike:1", "model") { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> Deimos + // REMOVE_START + assert_eq!(res, "Deimos"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1 model: {e}"); + return; + } + }; + + match r.hget("bike:1", "price") { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> 4972 + // REMOVE_START + assert_eq!(res, "4972"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1 price: {e}"); + return; + } + }; + + match r.hgetall("bike:1") { + Ok(res) => { + let res: Vec<(String, String)> = res; + println!("{res:?}"); + // >>> [("model", "Deimos"), ("brand", "Ergonom"), ("type", "Enduro bikes"), ("price", "4972")] + // REMOVE_START + assert_eq!(res.len(), 4); + assert_eq!(res[0].0, "model"); + assert_eq!(res[0].1, "Deimos"); + assert_eq!(res[1].0, "brand"); + assert_eq!(res[1].1, "Ergonom"); + assert_eq!(res[2].0, "type"); + assert_eq!(res[2].1, "Enduro bikes"); + assert_eq!(res[3].0, "price"); + assert_eq!(res[3].1, "4972"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + // STEP_END + + // STEP_START hmget + match r.hmget("bike:1", &["model", "price"]) { + Ok(res) => { + let res: Vec = res; + println!("{res:?}"); // >>> ["Deimos", "4972"] + // REMOVE_START + assert_eq!(res.len(), 2); + assert_eq!(res[0], "Deimos"); + assert_eq!(res[1], "4972"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + // STEP_END + + // STEP_START hincrby + if let Ok(res) = r.hincr("bike:1", "price", 100) { + let res: i32 = res; + println!("{res}"); // >>> 5072 + // REMOVE_START + assert_eq!(res, 5072); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1", "price", -100) { + let res: i32 = res; + println!("{res}"); // >>> 4972 + // REMOVE_START + assert_eq!(res, 4972); + // REMOVE_END + } + // STEP_END + + // STEP_START incrby_get_mget + if let Ok(res) = r.hincr("bike:1:stats", "rides", 1) { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "rides", 1) { + let res: i32 = res; + println!("{res}"); // >>> 2 + // REMOVE_START + assert_eq!(res, 2); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "rides", 1) { + let res: i32 = res; + println!("{res}"); // >>> 3 + // REMOVE_START + assert_eq!(res, 3); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "crashes", 1) { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + if let Ok(res) = r.hincr("bike:1:stats", "owners", 1) { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + match r.hget("bike:1:stats", "rides") { + Ok(res) => { + let res: i32 = res; + println!("{res}"); // >>> 3 + // REMOVE_START + assert_eq!(res, 3); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1:stats rides: {e}"); + return; + } + }; + + match r.hmget("bike:1:stats", &["crashes", "owners"]) { + Ok(res) => { + let res: Vec = res; + println!("{res:?}"); // >>> [1, 1] + // REMOVE_START + assert_eq!(res.len(), 2); + assert_eq!(res[0], 1); + assert_eq!(res[1], 1); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1:stats crashes and owners: {e}"); + return; + } + }; + // STEP_END + } +} diff --git a/local_examples/rust-sync/dt-string.rs b/local_examples/rust-sync/dt-string.rs new file mode 100644 index 000000000..46f4ac8da --- /dev/null +++ b/local_examples/rust-sync/dt-string.rs @@ -0,0 +1,149 @@ +// EXAMPLE: set_tutorial +#[cfg(test)] +mod strings_tests { + // STEP_START import + use redis::{Commands, ExistenceCheck}; + // STEP_END + + #[test] + fn run() { + let mut r = match redis::Client::open("redis://127.0.0.1") { + Ok(client) => { + match client.get_connection() { + Ok(conn) => conn, + Err(e) => { + println!("Failed to connect to Redis: {e}"); + return; + } + } + }, + Err(e) => { + println!("Failed to create Redis client: {e}"); + return; + } + }; + + // STEP_START set_get + if let Ok(res) = r.set("bike:1", "Deimos") { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.get("bike:1") { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> Deimos + // REMOVE_START + assert_eq!(res, "Deimos"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + // STEP_END + + // STEP_START setnx_xx + if let Ok(res) = r.set_options("bike:1", "bike", redis::SetOptions::default().conditional_set(ExistenceCheck::NX)) { + let res: bool = res; + println!("{res}"); // >>> false + // REMOVE_START + assert!(!res); + // REMOVE_END + } + + match r.get("bike:1") { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> Deimos + // REMOVE_START + assert_eq!(res, "Deimos"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + + if let Ok(res) = r.set_options("bike:1", "bike", redis::SetOptions::default().conditional_set(ExistenceCheck::XX)) { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.get("bike:1") { + Ok(res) => { + let res: String = res; + println!("{res}"); // >>> bike + // REMOVE_START + assert_eq!(res, "bike"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting bike:1: {e}"); + return; + } + }; + // STEP_END + + // STEP_START mset + if let Ok(res) = r.mset(&[("bike:1", "Deimos"), ("bike:2", "Ares"), ("bike:3", "Vanth")]) { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + match r.mget(&["bike:1", "bike:2", "bike:3"]) { + Ok(res) => { + let res: Vec = res; + println!("{res:?}"); // >>> ["Deimos", "Ares", "Vanth"] + // REMOVE_START + assert_eq!(res.len(), 3); + assert_eq!(res[0], "Deimos"); + assert_eq!(res[1], "Ares"); + assert_eq!(res[2], "Vanth"); + // REMOVE_END + }, + Err(e) => { + println!("Error getting values: {e}"); + return; + } + }; + // STEP_END + + // STEP_START incr + if let Ok(res) = r.set("total_crashes", 0) { + let res: String = res; + println!("{res}"); // >>> OK + // REMOVE_START + assert_eq!(res, "OK"); + // REMOVE_END + } + + if let Ok(res) = r.incr("total_crashes", 1) { + let res: i32 = res; + println!("{res}"); // >>> 1 + // REMOVE_START + assert_eq!(res, 1); + // REMOVE_END + } + + if let Ok(res) = r.incr("total_crashes", 10) { + let res: i32 = res; + println!("{res}"); // >>> 11 + // REMOVE_START + assert_eq!(res, 11); + // REMOVE_END + } + // STEP_END + } +} \ No newline at end of file