Redis 数据类型之哈希(Hash)类型

 2016年08月16日    461     声明


  1. 哈希(Hash)类型
  2. 哈希类型中的命令及使用

1. 哈希(Hash)类型

Redis 哈希(Hash)类型是字符串key和字符串value之间的映射,所以它十分适合用来表示一个对象信息。如:我们可以将一个用户对象存储为一个哈希类型,将用户的用户名、年龄、性别等属性各表示为一个key-value对。

哈希在某些应用场景中是一个非常有用存储方式,你可以将数以百万计的对象存储在一个很小的 Redis实例中。一个Redis 哈希值可存储232-1(40亿)个key-value对。


2. 哈希类型中的命令及使用

2.1 设置与取值

对哈希类型的操作,就是对一个哈希表的操作。对哈希表的设置及取值,就是对哈希表中字段的设置与取值。

2.1.1 HSET - 设置值

HSET key field value

设置哈希表keyfield字段值为value。如果key不存在,一个新的哈希表会被创建并进行HSET操作。如果field字段已经存在,旧值将被覆盖。

使用HSET命令,每次只能设置一个属性(字段)值,如果需要同时设置多个,可以使用HMSET命令。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值: 如果field是哈希表中的一个新字段,并且值设置成功,返回1。如果field已存在,且旧值已被新值覆盖,则返回0

使用示例

redis> hset abc f1 v1 
(integer) 1
redis> hget abc f1
"v1"
redis> hset abc f1 v2
(integer) 0
redis> hget abc f1
"v2"


2.1.2 HSETEX - 字段不存则设置其值

HSETNX key field value

HSET命令一样,HSETEX同样会设置哈希表keyfield字段值为value。但仅当field不存在才会设置。如果field字段已经存在,该操作无效。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值:设置成功,返回1。如果field已存在,则无操作且返回0

使用示例

redis> HSETNX nosql key-value-store redis
(integer) 1

# key-value-store 字段已存在,无操作
redis> HSETNX nosql key-value-store redis
(integer) 0


2.1.3 HGET - 获取指定字段值

HGET key field

返回哈希表keyfield字段的值。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值:key存在且field存在则返回其值。否则返回nil

使用示例

# 域存在
redis> HSET site itbilu itbilu.com
(integer) 1
redis> HGET site itbilu
"itbilu.com"

# 域不存在
redis> HGET site hehe
(nil)


2.1.4 HGETALL - 获取所有字段及值

HGETALL key

返回哈希表key中所有的field和其值。

复杂度、返回值:

  • 时间复杂度:O(N)N为哈希表的大小
  • 返回值:以列表形式返回哈希表中的字段和值。若哈希表不存在,否则返回一个空列表。

使用示例

redis> HSET people jack "Jack Sparrow"
(integer) 1
redis> HSET people gump "Forrest Gump"
(integer) 1

redis> HGETALL people
1) "jack"          # 字段
2) "Jack Sparrow"  # 值
3) "gump"
4) "Forrest Gump"


2.2 批量操作

字符串类型类似,哈希类型同样支持操作多个字段。

2.2.1 HMSET - 设置多个字段及值

HMSET key field value [field value ...]

将一个或多个field-value对设置到哈希表key。如果要设置的field已存在,则会覆盖其值。如果哈希表不存在,首先会创建再执行HMSET操作。

复杂度、返回值:

  • 时间复杂度:O(N)Nfield-value对的数量
  • 返回值:执行成功,返回OK。如果key不是哈希类型,则返回一个错误。

使用示例

redis> HMSET website google www.google.com yahoo www.yahoo.com
OK
redis> HGET website google
"www.google.com"
redis> HGET website yahoo
"www.yahoo.com"


2.2.2 HMGET - 返回多个字段值

HMGET key field [field ...]

返回哈希表key中,一个或多个指定的定段。如果指定的字段在哈希表中不存在,则返回一个nil。如果

复杂度、返回值:

  • 时间复杂度:O(N)N为指定字段的数量
  • 返回值:指定字段所关联值的列表。如果指定的key为哈段结构,则返回一个错误。

使用示例

# 一次设置多个字段
redis> HMSET pet dog "doudou" cat "nounou"    
OK

# 返回值多个字段值,返回顺序和传入参数的顺序一样
redis> HMGET pet dog cat fake_pet             
1) "doudou"
2) "nounou"
3) (nil)        # 不存在的字段返回nil值

# 非哈希结构
redis> set strKey "Hello World"
OK
redis> hmget strKey f1
(error) WRONGTYPE Operation against a key holding the wrong kind of value


2.3 字段/值操作

哈希类型支持单独字段或值,我们可以将不需要的字段删除、判断字段是否存在等;也可以不指定字段,而只获取所有字段的值。

2.3.1 HDEL - 字段删除

HDEL key field [field ...]

返回哈希表key中一个或多个指定字段,不存在的字段将被忽略。

复杂度、返回值:

  • 时间复杂度:O(N)N为要删除的字段数量
  • 返回值:被成功删除的字段数。

使用示例

# 测试数据
redis> HGETALL abbr
1) "a"
2) "apple"
3) "b"
4) "banana"
5) "c"
6) "cat"
7) "d"
8) "dog"

# 删除单个字段
redis> HDEL abbr a
(integer) 1

# 删除不存在的字段
redis> HDEL abbr not-exists-field
(integer) 0

# 删除多个字段
redis> HDEL abbr b c
(integer) 2

redis> HGETALL abbr
1) "d"
2) "dog"


2.3.2 HEXISTS - 判断字段是否存在

HEXISTS key field

判断哈希表key中字段field是否存在。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值:哈希表及指定字段存在,返回1。哈希表或指定字段不存在,返回0

使用示例

redis> HEXISTS phone myphone
(integer) 0
redis> HSET phone myphone nokia-1110
(integer) 1
redis> HEXISTS phone myphone
(integer) 1


2.3.3 HKEYS - 返回所有字段

HKEYS key

返回哈希表key中所有的字段。

复杂度、返回值:

  • 时间复杂度:O(N)N为哈希表的大小
  • 返回值:哈希表存在,返回字段列表。哈希表不存在,返回空列表。

使用示例

# 哈希表非空
redis> HMSET website google www.google.com yahoo www.yahoo.com
OK
redis> HKEYS website
1) "google"
2) "yahoo"

# 空哈希表不存在
redis> EXISTS fake_key
(integer) 0
redis> HKEYS fake_key
(empty list or set)


2.3.4 HLEN - 返回字段数量

HLEN key

返回哈希表key中字段的数量。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值:哈希表存在,返回字段数。哈希表不存在,返回0

使用示例

redis> HSET db redis redis.com
(integer) 1
redis> HSET db mysql mysql.com
(integer) 1
redis> HLEN db
(integer) 2

redis> HSET db mongodb mongodb.org
(integer) 1
redis> HLEN db
(integer) 3


2.3.5 HVALS - 返回所有字段值

HVALS key

返回哈希表key中所有字段的值。

复杂度、返回值:

  • 时间复杂度:O(N)N为哈希表的大小
  • 返回值:哈希表存在,返回字段值的列表。哈希表不存在,返回空列表。

使用示例

# 非空哈希表
redis> HMSET website google www.google.com yahoo www.yahoo.com
OK
redis> HVALS website
1) "www.google.com"
2) "www.yahoo.com"


# 空哈希表/不存在的key
redis> EXISTS not_exists
(integer) 0
redis> HVALS not_exists
(empty list or set)


2.4 自增

如果字段中存储的是数字值,我们可以对其进行加/减法操作。

2.4.1 HINCRBY - 为指定字段值增加

HINCRBY key field increment

为哈希表key中的指定字段field增加一个增量increment。增量也可以为负数,相当于对为指定字段进行减法操作。

如果哈希表不存在,则会创建一个哈希表,再执行HINCRBY操作。如果指定字段field不存在,那么会首先初始化为0,再执行HINCRBY

如果为非数字值执行HINCRBY操作,则返回一个错误。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值:执行HINCRBY操作后,哈希表key中字段field的值。

使用示例

# increment 为正数

# 对空域进行设置
redis> HEXISTS counter page_view
(integer) 0
redis> HINCRBY counter page_view 200
(integer) 200
redis> HGET counter page_view
"200"

# increment 为负数
redis> HGET counter page_view
"200"
redis> HINCRBY counter page_view -50
(integer) 150
redis> HGET counter page_view
"150"

# 尝试对字符串值的字段执行HINCRBY命令
redis> HSET myhash string hello,world    
(integer)
redis> HGET myhash string
"hello,world"
redis> HINCRBY myhash string 1  
(error) ERR hash value is not an integer
redis> HGET myhash string
"hello,world"    # 原值不变


2.4.2 HINCRBYFLOAT - 为指定字段值增加浮点数

HINCRBYFLOAT key field increment

为哈希表key中的指定字段field增加一个浮点数增量increment。增量也可以为负数,相当于对为指定字段进行减法操作。

如果哈希表不存在,则会创建一个哈希表,再执行HINCRBYFLOAT操作。如果指定字段field不存在,那么会首先初始化为0,再执行HINCRBYFLOAT

如果为非数字值执行HINCRBYFLOAT操作,则返回一个错误。

复杂度、返回值:

  • 时间复杂度:O(1)
  • 返回值:执行HINCRBYFLOAT操作后,哈希表key中字段field的值。

使用示例

# 值和增量都是普通小数
redis> HSET mykey field 10.50
(integer) 1
redis> HINCRBYFLOAT mykey field 0.1
"10.6"

# 值和增量都是指数符号
redis> HSET mykey field 5.0e3
(integer) 0
redis> HINCRBYFLOAT mykey field 2.0e2
"5200"

# 对不存在的键执行 HINCRBYFLOAT
redis> EXISTS price
(integer) 0
redis> HINCRBYFLOAT price milk 3.5
"3.5"
redis> HGETALL price
1) "milk"
2) "3.5"

# 对不存在的字段进行 HINCRBYFLOAT
redis> HGETALL price
1) "milk"
2) "3.5"
redis> HINCRBYFLOAT price coffee 4.5
"4.5"
redis> HGETALL price
1) "milk"
2) "3.5"
3) "coffee"
4) "4.5"