redis系列:通過demo學習hash命令

NO IMAGE

前言

這一篇文章將講述Redis中的hash類型命令,同樣也是通過demo來講述,其他部分這裡就不在贅述了。

項目Github地址:github.com/rainbowda/l…

案例

demo功能是記錄日誌,整個demo的大致頁面如下

redis系列:通過demo學習hash命令

準備工作

首先定義一個key的前綴,已經存儲自增id的key

private static final String CONTACTS_KEY_PREFIX = "contacts:";
private static final String CONTACTS_ID_KEY = "contactsID";

通訊錄相關的key將會以contacts:1、contacts:2、contacts:3的形式存儲

redis操作對象

private RedisTemplate redisTemplate;
//string 命令操作對象
private ValueOperations valueOperations;
//hash 命令操作對象
private HashOperations hashOperatio

疑惑

如果讀者和我一樣是學Java的,剛聽到hash時的第一反應是這個不是一個算法嗎?當時我也是這樣想的。那麼先來看看hash在Redis中的結構,如下圖(圖片來源於Redis in Action)。

redis系列:通過demo學習hash命令

如果圖看不懂的,我再來介紹下。其實Redis中的hash結構就和mysql中的表類似,把key當做表名,一張表中有多個列名(sub-key),每個列有自己的值(value),然後這張表只能存放一條數據。不過,這裡的hash結構不會像mysql中固定好的,它可以很方便的增加刪除列,例如增加sub-key3刪除sub-key1.

redis系列:通過demo學習hash命令

新增

命令介紹

先來看看hash中關於新增的一些命令

命令用例描述
HSETHSET key field value設置 key 指定的哈希集中指定字段的值。
HSETNXHSETNX key field value當field不存在時,才能成功設置值
HMSETHMSET key field value [field value …]設置 key 指定的哈希集中指定字段的值(多個) 。

接下來看看demo中新增的功能,下圖中點擊+按鈕,然後在彈出框中填入name和phone屬性,點擊提交後整個新增流程結束。

redis系列:通過demo學習hash命令

來看看後臺的方法

@RequestMapping(value = "/add",method = RequestMethod.POST)
public boolean add(@RequestBody JSONObject contacts){
//獲取自增id
Long contactsId = valueOperations.increment(CONTACTS_ID_KEY, 1);
contacts.put("id",String.valueOf(contactsId));
//json轉map,然後存入redis
hashOperations.putAll(CONTACTS_KEY_PREFIX+contactsId,contacts.getInnerMap());
return true;
}
  1. 首先是獲得自增id

  2. 然後將id存入到前端傳過來的json對象中

  3. 調用hashOperations對象的putAll方法將對象傳入到Redis中。(putAll方法其實是調用了hmset命令,源碼如下)

public void putAll(K key, Map<? extends HK, ? extends HV> m) {
if (!m.isEmpty()) {
byte[] rawKey = this.rawKey(key);
Map<byte[], byte[]> hashes = new LinkedHashMap(m.size());
Iterator var5 = m.entrySet().iterator();
while(var5.hasNext()) {
Entry<? extends HK, ? extends HV> entry = (Entry)var5.next();
hashes.put(this.rawHashKey(entry.getKey()), this.rawHashValue(entry.getValue()));
}
//調用hMSet
this.execute((connection) -> {
connection.hMSet(rawKey, hashes);
return null;
}, true);
}
}

列表查詢

命令介紹

同樣先看看相關的獲取值命令

命令用例描述
HGETHGET key field返回 key 指定的哈希集中該字段所關聯的值
HGETALLHGETALL key返回 key 指定的哈希集中所有的字段和值。
HKEYSHKEYS key返回 key 指定的哈希集中所有字段的名字。
HMGETHMGET key field [field …]返回 key 指定的哈希集中指定字段的值。
HVALSHVALS key返回 key 指定的哈希集中所有字段的值。
HSCAN用於迭代Hash類型中的鍵值對。
HGET和HGETALL命令

來看看HGET和HGETALL在redis客戶端和java中是如何操作的

redis客戶端執行的命令如下

hset key field1 "Hi"
hset key field1 "Hello"
hsetnx key field1 "Hello"
hsetnx key field2 " redis"
hget key field1
hgetall key

執行結果如下

redis系列:通過demo學習hash命令

下面是java代碼

@Test
public void hGetAll() {
jedis.hset("key", "field1", "Hi");
redisTemplate.opsForHash().put("key", "field1", "Hello");
System.out.println(jedis.hsetnx("key", "field1", "Hello"));
System.out.println(redisTemplate.opsForHash().putIfAbsent("key", "field2", "Hello"));
System.out.println(jedis.hget("key", "field1"));
System.out.println(jedis.hgetAll("key"));
//spring redisTemplate
System.out.println(redisTemplate.opsForHash().get("key", "field1"));
System.out.println(redisTemplate.opsForHash().entries("key"));
}
HKEYS

redis客戶端執行的命令如下

hset hashKey field1 value1
hset hashKey field2 value2
hkeys hashKey

執行結果如下

redis系列:通過demo學習hash命令

下面是java代碼

@Test
public void hKeys() {
jedis.hset("hashKey", "field1", "value1");
jedis.hset("hashKey", "field2", "value2");
System.out.println(jedis.hkeys("hashKey"));
//spring redisTemplate
System.out.println(redisTemplate.opsForHash().keys("hashKey"));
/**
* 注:兩次結果返回的順序是不一樣的,
* 因為jedis.hkeys返回的是HashSet(內部使用HashMap)
* redisTemplate.opsForHash().keys返回的是LinkHashSet(內部使用LinkHashMap)
*/
}
HVALS

redis客戶端執行的命令如下

hmset key field1 value1 field2 value2 field3 value3
hvals key

執行結果如下

redis系列:通過demo學習hash命令

下面是java代碼

@Test
public void hVals() {
Map<String, String> map = new HashMap<>(3);
map.put("field1", "value1");
map.put("field2", "value2");
map.put("field3", "value3");
jedis.hmset("key", map);
System.out.println(jedis.hvals("key"));
//spring redisTemplate
System.out.println(redisTemplate.opsForHash().values("key"));
}

查詢方法代碼

接著寫個查詢方法,將新增的內容查詢出來

@RequestMapping(value = "/getList",method = RequestMethod.GET)
public List getList(){
List list = new ArrayList();
//獲取聯繫人的keys
Set<String> keys = redisTemplate.keys(CONTACTS_KEY_PREFIX+"*");
for (String key: keys) {
Map entries = hashOperations.entries(key);
list.add(entries);
}
return list;
}

這個hash查詢多個會不方便些,步驟如下

  1. 獲取相關的key
  2. 循環查找key相關的數據
  3. 將查詢出來的結果添加到list中,返回

添加屬性

redis系列:通過demo學習hash命令

來看看代碼

@RequestMapping(value = "/addAttr", method = RequestMethod.POST)
public boolean addAttr(@RequestBody JSONObject contacts){
String id = contacts.getString("id");
String fieldName = contacts.getString("fieldName");
String fieldValue = contacts.getString("fieldValue");
hashOperations.put(CONTACTS_KEY_PREFIX+id, fieldName, fieldValue);
return true;
}

其實就是用hset命令進行插入

hset contacts:1 address 北京9527號

刪除屬性

命令介紹

命令用例描述
HDELHDEL key field [field …]從 key 指定的哈希集中移除指定的域

redis客戶端執行的命令如下

hset hDelKey filed1 filedValue1
hdel hDelKey filed1
hdel hDelKey filed1

執行結果如下

redis系列:通過demo學習hash命令

現在來看看demo中的刪除屬性

redis系列:通過demo學習hash命令

代碼如下

@RequestMapping(value = "/delAttr", method = RequestMethod.POST)
public boolean delAttr(@RequestBody JSONObject contacts){
String id = contacts.getString("id");
String fieldName = contacts.getString("fieldName");
hashOperations.delete(CONTACTS_KEY_PREFIX+id, fieldName);
return true;
}

其他命令

命令用例描述
HEXISTSHEXISTS key field返回hash裡面field是否存在
HINCRBYHINCRBY key field increment增加 key 指定的哈希集中指定字段的數值
HINCRBYFLOATHINCRBYFLOAT key field increment同上,加的是浮點型
HLENHLEN key返回 key 指定的哈希集包含的字段的數量。
HSTRLENHSTRLEN key field返回hash指定field的value的字符串長度

建議學習的人最好每個命令都去敲下,加深印象。下面詩句送給你們。

紙上得來終覺淺,絕知此事要躬行。————出自《冬夜讀書示子聿》

相關文章

redis系列:RDB持久化與AOF持久化

redis系列:通過文章點贊排名案例學習sortedset命令

redis系列:通過共同好友案例學習set命令

redis系列:通過demo學習list命令