Rust development - using rust to implement hset in Redis

1. hset in Redis

HSETis 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.

HSETThe basic syntax of the command is:

HSET key field value
  • keyis the name of the hash table.
  • fieldis the name of the field whose value is to be set.
  • valueis 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:usernamejohndoeHGET

HGET user:1001 username

The above command will return the value of the field in the user:1001 hash table, that is, . usernamejohndoe

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

HSETThe 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:
Insert image description here

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());
}

Guess you like

Origin blog.csdn.net/matt45m/article/details/127533481