Map 集合形式为 key-map,也就是说 value 其实是以 map 形式展示的,本质和 String 类型没啥不一样,还是简单的 key - value
127.0.0.1:6379> HSET stus id1 222 # 插入 (integer) 1 127.0.0.1:6379> HGET stus id1 # 获取 "222" 127.0.0.1:6379> HMSET stus id2 333 id3 444 # 同时插入多个值 OK 127.0.0.1:6379> HMGET stus id1 id2 id3 # 同时获取 key 中多个 field 的值 1) "222" 2) "333" 3) "444" 127.0.0.1:6379> HGETALL stus # 获取 key 中所有 field - value 值(以 map 形式展示) 1) "id1" 2) "222" 3) "id2" 4) "333" 5) "id3" 6) "444" 127.0.0.1:6379> HDEL stus id3 # 删除指定 key 中的 field (integer) 1 127.0.0.1:6379> HGETALL stus 1) "id1" 2) "222" 3) "id2" 4) "333" 127.0.0.1:6379> HKEYS stus # 获取 key 中 所有的 field 1) "id1" 2) "id2" 127.0.0.1:6379> HVALS stus # 获取 key 中所有的 field 中的值 1) "222" 2) "333"
127.0.0.1:6379> HGETALL stus 1) "id1" 2) "222" 3) "id2" 4) "333" 127.0.0.1:6379> HEXISTS stus id3 # 判断指定 key 中的 field 是否存在 (integer) 0 127.0.0.1:6379> HEXISTS stus id2 (integer) 1 127.0.0.1:6379> HSETNX stus id3 444 # 判断指定 key 中的 field 是否存在,不存在则插入 (integer) 1 127.0.0.1:6379> HSETNX stus id3 444 (integer) 0 127.0.0.1:6379> HGETALL stus 1) "id1" 2) "222" 3) "id2" 4) "333" 5) "id3" 6) "444"
127.0.0.1:6379> HGETALL stus # 获取所有值(以 map 形式展示) 1) "id1" 2) "222" 3) "id2" 4) "333" 5) "id3" 6) "444" 127.0.0.1:6379> HLEN stus (integer) 3
127.0.0.1:6379> HINCRBY stus id3 111 # 指定 key 中的 field 的值按照指定数自增 (integer) 555 127.0.0.1:6379> HGETALL stus 1) "id1" 2) "222" 3) "id2" 4) "333" 5) "id3" 6) "555" 127.0.0.1:6379> HINCRBY stus id3 -111 # 指定 key 中的 field 的值按照指定数自增,这里和 String 不一样,增量是负数则表示自减 (integer) 444 127.0.0.1:6379> HGETALL stus 1) "id1" 2) "222" 3) "id2" 4) "333" 5) "id3" 6) "444"
以用户 id 为 key,商品 id 为 field,商品数量为 value,可以构成了购物车的 3 个要素。
hash 类型的(key, field, value)的结构与对象的(对象 id, 属性, 值)的结构相似,也可以用来存储对象。
在介绍 String 类型的应用场景时有所介绍,String + Json 也是存储对象的一种方式,那么存储对象时,到底用 String + Json 还是用 Hash 呢?
当对象的某个属性需要频繁修改时,不适合用 String + Json,因为它不够灵活,每次修改都需要重新将整个对象序列化并赋值,如果使用 Hash 类型,则可以针对某个属性单独修改,没有序列化,也不需要修改整个对象。比如,商品的价格、销量、关注数、评价数等可能经常发生变化的属性,就适合存储在 Hash 类型里。
当然,不常变化的属性存储在 Hash 类型里也没有问题,比如商品名称、商品描述、上市日期等。但是,当对象的某个属性不是基本类型或字符串时,使用 Hash 类型就必须手动进行复杂序列化,比如,商品的标签是一个标签对象的列表,商品可领取的优惠券是一个优惠券对象的列表等,即使以 coupons(优惠券)作为 field,value 想存储优惠券对象列表也还是要使用 Json 来序列化,这样的话序列化工作就太繁琐了,不如直接用 String + Json 的方式存储商品信息来的简单。
综上,一般对象用 String + Json 存储,对象中某些频繁变化的属性抽出来用hash存储。