HGET:获取字段的值

HGET 命令可以根据用户给定的字段,从散列中获取该字段的值:

HGET hash field

例如,对于图 3-7 所示的两个散列键来说,执行以下命令可以从 article::10086 散列中获取 author 字段的值:

redis> HGET article::10086 author
"peter"

而执行以下命令则可以从 article::10086 散列中获取 created_at 字段的值:

redis> HGET article::10086 created_at
"1442744762.631885"
image 2025 01 02 17 34 35 692
Figure 1. 图3-7 两个散列

再例如,如果我们想要从 account::54321 散列中获取 email 字段的值,那么可以执行以下命令:

redis> HGET account::54321 email
"peter1984@spam_mail.com"

处理不存在的字段或者不存在的散列

如果用户给定的字段并不存在于散列当中,那么 HGET 命令将返回一个空值。

举个例子,在以下代码中,我们尝试从 account::54321 散列里面获取 location 字段的值,但由于 location 字段并不存在于 account::54321 散列当中,所以 HGET 命令将返回一个空值:

redis> HGET account::54321 location
(nil)

尝试从一个不存在的散列里面获取一个不存在的字段值,得到的结果也是一样的:

redis> HGET not-exists-hash not-exists-field
(nil)

其它信息

  • 复杂度:O(1)。

  • 版本要求:HGET 命令从 Redis 2.0.0 版本开始可用。

示例:实现短网址生成程序

为了给用户提供更多发言空间,并记录用户在网站上的链接点击行为,大部分社交网站都会将用户输入的网址转换为相应的短网址。比如,如果我们在新浪微博中发言时输入网址 http://redisdoc.com/geo/index.html ,那么微博将把这个网址转换为相应的短网址 http://t.cn/RqRRZ8n ,当用户访问这个短网址时,微博在后台就会对这次点击进行一些数据统计,然后再引导用户的浏览器跳转到 http://redisdoc.com/geo/index.html 上面。

创建短网址本质上就是要创建出短网址 ID 与目标网址之间的映射,并在用户访问短网址时,根据短网址的 ID 从映射记录中找出与之相对应的目标网址。比如在前面的例子中,微博的短网址程序就将短网址 http://t.cn/RqRRZ8n 中的 ID 值 RqRRZ8n 映射到了 http://redisdoc.com/geo/index.html 这个网址上面,当用户访问短网址 http://t.cn/RqRRZ8n 时,程序就会根据这个短网址的 ID 值 RqRRZ8n 找出与之对应的目标网址 http://redisdoc.com/geo/index.html ,并将用户引导至目标网址上面去。

作为示例,图 3-8 展示了几个微博短网址ID与目标网址之间的映射关系。

image 2025 01 02 17 38 58 966
Figure 2. 图3-8 微博短网址ID与目标网址映射关系示例

因为 Redis 的散列非常适合用来存储短网址 ID 与目标网址之间的映射,所以我们可以基于 Redis 的散列实现一个短网址程序,代码清单3-1展示了一个这样的例子。

代码清单3-1 使用散列实现的短网址程序:/hash/shorty_url.py
from base36 import base10_to_base36

ID_COUNTER = "ShortyUrl::id_counter"
URL_HASH = "ShortyUrl::url_hash"

class ShortyUrl:

    def __init__(self, client):
        self.client = client

    def shorten(self, target_url):
        """
        为目标网址创建并储存相应的短网址 ID 。
        """
        # 为目标网址创建新的数字 ID
        new_id = self.client.incr(ID_COUNTER)
        # 通过将 10 进制数字转换为 36 进制数字来创建短网址 ID
        # 比如说,10 进制数字 10086 将被转换为 36 进制数字 7S6
        short_id = base10_to_base36(new_id)
        # 把短网址 ID 用作字段,目标网址用作值,
        # 将它们之间的映射关系储存到散列里面
        self.client.hset(URL_HASH, short_id, target_url)
        return short_id

    def restore(self, short_id):
        """
        根据给定的短网址 ID ,返回与之对应的目标网址。
        """
        return self.client.hget(URL_HASH, short_id)

ShortyUrl 类的 shorten() 方法负责为输入的网址生成短网址 ID,它的工作包括以下 4 个步骤:

  1. 为每个给定的网址创建一个十进制数字 ID。

  2. 将十进制数字 ID 转换为三十六进制,并将这个三十六进制数字用作给定网址的短网址 ID,这种方法在数字 ID 长度较大时可以有效地缩短数字 ID 的长度。代码清单 3-2 展示了将数字从十进制转换成三十六进制的 base10_to_base36 函数的具体实现。

  3. 将短网址 ID 和目标网址之间的映射关系存储到散列中。

  4. 向调用者返回刚刚生成的短网址 ID。

代码清单3-2 将十进制数字转换成三十六进制数字的程序:/hash/base36.py
def base10_to_base36(number):
    alphabets = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    result = ""

    while number != 0 :
        number, i = divmod(number, 36)
        result = (alphabets[i] + result)

    return result or alphabets[0]

restore() 方法要做的事情和 shorten() 方法正好相反,它会从存储着映射关系的散列里面取出与给定短网址 ID 相对应的目标网址,然后将其返回给调用者。

以下代码简单地展示了使用 ShortyUrl 程序创建短网址 ID 的方法,以及根据短网址 ID 获取目标网址的方法:

>>> from redis import Redis
>>> from shorty_url import ShortyUrl
>>> client = Redis(decode_responses=True)
>>> shorty_url = ShortyUrl(client)
>>> shorty_url.shorten("RedisGuide.com") # 创建短网址ID
'1'
>>> shorty_url.shorten("RedisBook.com")
'2'
>>> shorty_url.shorten("RedisDoc.com")
'3'
>>> shorty_url.restore("1") # 根据短网址ID查找目标网址
'RedisGuide.com'
>>> shorty_url.restore("2")
'RedisBook.com'

图3-9 展示了上面这段代码在数据库中创建的散列结构。

image 2025 01 02 17 43 49 980
Figure 3. 图3-9 短网址程序在数据库中创建的散列结构