跟著Redis入門指南學習
第三章 5種資料類型----hash類型
3.3(散列類型)
redis採用幾點結構以健值對的形式儲存資料的,而散列類型(hash)的健值也是一種字典結構,其儲存了欄位和欄位值的映射。但欄位值只能是字串,不支援其他資料類型。換句話說,散列類型不能嵌套其他的資料類型。一個散列類型健可以包含至多2^32 -1個欄位。
提示:除了散列類型,redis的其他資料類型同樣不支援資料類型嵌套。比如集合類型的每個元素都只能是字串,而不能是另一個集合或者散列表等。
散列類型適合儲存物件:使用物件類別和ID構成健名,使用欄位表示的對象的屬性,而欄位值則儲存屬性值。例如要儲存ID為2的汽車對象,可以分別使用名為color、name和price的3個欄位來儲存該汽車的顏色、名稱和價格。
在關聯式資料庫中如果要儲存汽車對象,資料是以二維表的形式儲存的,這就要所有的記錄都擁有同樣的屬性,無法單獨為某條幾率增減屬性,如果想為ID為1的汽車增加生產日期屬性,就需要把資料表更改添加一個data屬性,對於之前的資料data就是冗餘的。可想而知當不同的記錄需要不同的屬性時,表的欄位數量會越來越多以至於難以維護。而且當使用ORM將關聯式資料庫中的對象實體映射成程式中的實體時,修改表的結構往往意味著要中斷服務(重啟網站程式)。為了防止這些問題,在關聯式資料庫中儲存這種半結構化資料還需要額外的表才行。
而redis的散列類型則不存在這個問題。redis並不要求每個健都依據此結構儲存,我們完全可以自由的位任何健增減欄位而不影響其他健。
3.3.2 命令
1.賦值與取值
hset key field valuehget key fielshmset key field value [field value ...]hmget key field [field ...]hgetall key
hset命令用來給欄位賦值,而hget命令來擷取欄位的值,用法如下:
127.0.0.1:6379[1]> hset car price 500(integer) 1127.0.0.1:6379[1]> hset car price 666(integer) 0127.0.0.1:6379[1]> hget car price"666"127.0.0.1:6379[1]> hset car name bmw(integer) 1127.0.0.1:6379[1]> hget car name"bmw"
hset命令的方便之處在於不區分插入和更新操作,這意味著修改資料時不用事先判斷欄位是否存在來決定要執行的是插入操作(insert)還是更新操作(update)。當執行的是插入時(即之前欄位不存在)hset命令返回1,當執行的是更新操作時,返回的是0.當健本身不存在時,hset命令還會自動建立它。
提示:在redis中每個健都屬於一個明確的資料類型,如通過hset命令建立的健是散列類型,通過set命令建立的健是字串類型等。使用一種資料類型的命令操作另一種資料類型的健會提示錯誤:err operation against a key holding the wrong kind of value.
127.0.0.1:6379[1]> hmget car name price1) "bmw"2) "666"127.0.0.1:6379[1]> hmset car color blue data 2016OK127.0.0.1:6379[1]> hmget car name price color data1) "bmw"2) "666"3) "blue"4) "2016"127.0.0.1:6379[1]> hgetall car1) "price"2) "666"3) "name"4) "bmw"5) "color"6) "blue"7) "data"8) "2016"
如果想擷取健中所有欄位和欄位值卻不知道健中有哪些欄位時,應該使用hgetall命令,返回的結果是欄位和欄位值組成的列表,不是很直觀,好在很多語言的redis用戶端會將hgetall的返回結果封裝成程式設計語言中的對象,處理起來就非常方便了。例如,在node.js中:
redis.hgetall("car",function(error,car){//hgetall方法的傳回值被封裝成了javaSript的對象 console.log(car.price); console.log(car.name);});
2.判斷欄位是否存在
hexists key field
若果存在返回1,否則返回0。(如果健不存在也會返回0)。
127.0.0.1:6379[1]> hexists car model(integer) 0127.0.0.1:6379[1]> hexists car name(integer) 1127.0.0.1:6379[1]> hexists nocar name(integer) 0
3.欄位不存在時賦值
hsetnx key field value
hsetnx命令與hset命令類似,區別在於如果欄位已經存在,hsetnx命令將不執行任何操作。hsetnx命令是原子操作,不用擔心競態條件。
4.增加數字
hincrby key field increment
hincrby 與incrby命令類似,可以是欄位值增加指定的整數,散列類型沒有hincr命令,但可以通過hincrby key field 1 來實現。
127.0.0.1:6379[1]> hincrby ca price 200(integer) 200127.0.0.1:6379[1]> hget car price"666"127.0.0.1:6379[1]> hincrby car price 200(integer) 866127.0.0.1:6379[1]> hget ca price"200"
如果健不存在,hincrby命令會自動建立該健並預設設定price 欄位在執行命令前的值為0.命令的傳回值是增值後的欄位值。
5.刪除欄位
hdel key field [field ...]
hdel 命令可以刪除一個或多個欄位,傳回值是被刪除的欄位個數:
127.0.0.1:6379[1]> hdel car price name(integer) 2127.0.0.1:6379[1]> hdel car color name(integer) 1
3.3.4 命令拾遺
1.只擷取欄位名或欄位值
hkeys keyhvals key
127.0.0.1:6379[1]> hkeys car1) "data"2) "name"3) "color"127.0.0.1:6379[1]> hvals car1) "2016"2) "bmw"3) "blue"
2.擷取欄位數量
hlen key
127.0.0.1:6379[1]> hlen car(integer) 3