1. hset in Redis
HSET
is a command in Redis used to set the value of a specified field in a hash data structure. A hash is a data structure similar to a dictionary or map that stores a collection of key-value pairs, where each key contains multiple fields and the values associated with those fields.
Hash tables are stored in Redis as key-value pairs and are accessed through unique key names. Each key can be associated with multiple fields and corresponding values, making hash tables ideal for storing attributes of objects, entities, or records.
HSET
The basic syntax of the command is:
HSET key field value
key
is the name of the hash table.field
is the name of the field whose value is to be set.value
is the value to be stored in the field.
For example, assuming we have a hash table of user information with the key user:1001
, we can use the HSET
command to set the user ID to 1001
’s username is johndoe
:
HSET user:1001 username johndoe
This command will set the value of the field in the user:1001
hash table to . Afterwards, you can use the command to get the value of the specified field:username
johndoe
HGET
HGET user:1001 username
The above command will return the value of the field in the user:1001
hash table, that is, . username
johndoe
The advantage of hash table is that it can efficiently store and retrieve a large number of field-value pairs, which is especially suitable for scenarios where object attributes need to be stored and queried. In addition to the HSET
command, Redis also provides other commands related to hash table operations, such as HGETALL
for obtaining all fields and values in the hash table. List, HDEL
is used to delete one or more fields, etc.
2. Application of Hset
HSET
The command has many application scenarios in Redis, especially when it is necessary to store and retrieve object properties. Here are some common use cases of the HSET
command in practice:
1. Store user information
Storing user information is one of the common use cases for the HSET
command. For example, storing a user's username, email, age, etc.:
HSET user:1001 username johndoe
HSET user:1001 email [email protected]
HSET user:1001 age 30
2. Cache object properties
Storing object properties in cache is one way to improve read performance. For example, to store product information:
HSET product:5001 name "Product Name"
HSET product:5001 price 29.99
HSET product:5001 category "Electronics"
3. Record real-time data
Used to record real-time data, such as indicator data in real-time monitoring systems:
HSET stats:today visits 1000
HSET stats:today purchases 50
HSET stats:today revenue 2500.00
4. Cache object status
Store object state or configuration information in the cache:
HSET server:status hostname "Server-A"
HSET server:status status "Running"
HSET server:status users_connected 50
5. Store form data
In web development, you can use a hash table to store form data, such as form information submitted by users:
HSET form:submission:1001 name "Alice"
HSET form:submission:1001 email "[email protected]"
HSET form:submission:1001 message "This is a sample message."
6. Object attribute index
Used to create indexes on object properties for easier retrieval and querying. For example, to store a user's interest tags in the database:
HSET interest:books user:1001 1
HSET interest:music user:1001 1
HSET interest:travel user:1001 1
The hash data structure provides flexibility and efficiency, and can store and manage multiple fields and values, so it is widely used in many scenarios that require a collection of key-value pairs.
3. Use Rust to implement Hset table
In Rust, there is no Hset library API. If you want to implement hset like Redis, you have to implement it yourself. The structure I want to implement here is to record the comments of an article, the ID of the comment, and the content of the reply comment. ID, the storage content is as follows:
Implementation code:
use std::{
collections::HashMap, borrow::Borrow};
use std::hash::Hash;
#[derive(Clone)]
pub struct Value<K,V>
{
pub value : HashMap<K,V>,
}
impl <K,V> Value<K,V>
{
pub fn new() ->Self
{
Self {
value: HashMap::new()}
}
}
#[derive(Clone)]
pub struct Field<K,V>
{
pub field : Value<K,V>,
pub ex_field : HashMap<K,Value<K,V>>,
}
impl<K,V> Field<K,V>
{
pub fn new() ->Self
{
Self {
field: Value::new(), ex_field: HashMap::new()}
}
}
#[derive(Clone,Default)]
pub struct HashSet<K,V>
{
pub set : HashMap<K,Field<K,V>>,
}
impl<K,V> HashSet<K,V>
where
K:Hash + Eq,
V:Copy,
{
pub fn new() ->Self
{
Self {
set: HashMap::new()}
}
pub fn insert(&mut self, key : K, field : K, value : V,sub_field : Option<K>) ->bool
{
match sub_field
{
Some(ex_key) =>
{
match self.set.get_mut(&key)
{
Some(f_value) =>
{
match f_value.ex_field.get_mut(&ex_key)
{
Some(ex_value) =>
{
match ex_value.value.get_mut(&field)
{
Some(_ex) => false,
None =>
{
ex_value.value.insert(field, value);
true
},
}
},
None =>
{
let mut sub : Value<K,V> = Value::new();
sub.value.insert(field, value);
f_value.ex_field.insert(ex_key,sub);
true
},
}
},
None =>
{
let mut sub : Value<K,V> = Value::new();
sub.value.insert(field, value);
let mut m_field : Field<K,V> = Field::new();
m_field.ex_field.insert(ex_key, sub);
self.set.insert(key, m_field);
true
},
}
},
None =>
{
match self.set.get_mut(&key)
{
Some(set) =>
{
match set.field.value.get_mut(&field)
{
Some(_v) => false,
None =>
{
set.field.value.insert(field, value);
true
}
}
},
None =>
{
let mut m_field : Field<K,V> = Field::new();
m_field.field.value.insert(field, value);
self.set.insert(key, m_field);
true
}
}
},
}
}
pub fn remove(&mut self, key : K , field : K, sub_field : Option<K>)->bool
{
match sub_field
{
Some(ex_key) =>
{
match self.set.get_mut(&key)
{
Some(f_value) =>
{
match f_value.ex_field.get_mut(&ex_key)
{
Some(ex_value) =>
{
match ex_value.value.get_mut(&field)
{
Some(_ex) =>
{
ex_value.value.remove(&field);
true
}
None => false,
}
},
None => false
}
},
None => false
}
},
None =>
{
match self.set.get_mut(&key)
{
Some(set) =>
{
match set.field.value.get_mut(&field)
{
Some(_v) =>
{
set.field.value.remove(&field);
true
},
None => false
}
},
None =>false
}
},
}
}
pub fn get_field_value(&self,key : K, field : K) -> Result<V,bool>
{
match self.set.get(&key)
{
Some(value) =>
{
match value.field.value.get(&field)
{
Some(v) => Ok(*v),
None => Err(false),
}
},
None => Err(false)
}
}
pub fn get_ex_field_value(&self,key:K, field : K,sub_field : K) ->Result<V,bool>
{
match self.set.get(&key)
{
Some(value) =>
{
match value.ex_field.get(&sub_field)
{
Some(sub_value) =>
{
match sub_value.value.get(&field)
{
Some(v) => Ok(*v),
None => Err(false),
}
}
None => Err(false)
}
}
None => Err(false)
}
}
}
pub fn hset_size(hset : HashSet<&str,u64>) ->usize
{
let mut size : usize = 0;
for (k,v) in hset.set
{
let f_size = field_size(v);
size += k.len() + f_size;
}
size
}
pub fn field_size(field : Field<&str,u64>) -> usize
{
let mut f_size : usize = 0;
for(m_k,_m_v) in field.field.value
{
f_size += m_k.len() + 8;
}
let mut ex_size : usize = 0;
for(f_k,f_v) in field.ex_field
{
let mut sub_size : usize = 0;
for (s_k, _s_v) in f_v.value.iter()
{
sub_size += s_k.len() + 8;
}
ex_size += sub_size + f_k.len();
}
f_size + ex_size
}
use core::num;
use std::{
mem, collections::{
HashMap}, time::{
SystemTime, UNIX_EPOCH}, borrow::{
Borrow, BorrowMut}, cell::RefCell};
pub struct CanisterState
{
data : HashSet<String,u64>,
}
fn main()
{
let v : Vec<u8> = vec![65];
let m = String::from_utf8(v.clone()).unwrap();
print!("{}\n",m);
LIKES.with(|like_ref|
{
let hset : CanisterState = CanisterState {
data: mem::take(&mut like_ref.borrow_mut()) };
});
let mut hset : HashSet<&str,u64> = HashSet::new();
hset.insert("唐诗", "王维",time(),Some("10"));
hset.insert("唐", "李白",time(),None);
hset.insert("诗", "李白",time(),None);
hset.insert("宋", "李清照",time(),Some("1"));
hset.insert("宋词", "李清照",time(),None);
let r = hset.get_field_value("唐诗", "李白");
match r
{
Ok(v) => print!("{}\n",v),
Err(e) => print!("{}\n",e),
}
print!("{}\n",hset_size(hset.clone()));
let _ = hset.remove("matt", "200", None);
hset.insert("matt".to_string(), "300".to_string(),
"200".to_string(),None);
hset.insert("matt".to_string(), "200".to_string(),
"200".to_string(),None);
hset.insert("45m".to_string(), "300".to_string(),
"200".to_string(),None);
hset.insert("45m".to_string(), "200".to_string(),
"200".to_string(),None);
/show(hset.clone());
}