《Redis入门指南》一5.2 Ruby与Redis

5.2 Ruby与Redis

Redis入门指南
Redis官方推荐的Ruby客户端是redis-rb1,也是各种语言的Redis客户端中最为稳定的一个。其主要代码贡献者就是Redis的开发者之一Pieter Noordhuis。

5.2.1 安装

使用gem install redis安装最新版本的redis-rb,目前的最新版本是3.0.2。

5.2.2 使用方法

创建到Redis的连接很简单:

require 'redis'
redis = Redis.new

该行代码会默认Redis的地址为127.0.0.1,端口为6379。如果需要更改地址或端口,可以使用:

redis = Redis.new(:host => '127.0.0.1', :port => 6379)

redis-rb的官方文档相对比较详细,所以具体的使用方法可以见其GitHub主页。这里从其中挑出几个比较有代表性的命令作为示例:

r.set('redis_db', 'great k / v storage') # => OK
r.get('redis_db')               # => "great k / v storage"
r.incrby('counter', 99)           # => 99
r.hmset('hash_dt', :key2, 'value2', :key3, 'value3') # => OK

5.2.3 简便用法

redis-rb最便捷的命令调用方法就是对SET和GET命令使用别名[],例如:

redis.set('key', 'value')
可以写成

redis['key'] = 'value'
同样

value = redis.get('key')
可以写成

value = redis['key']

另外,对于事务的返回值可以提前设置对结果的引用,就像这样:

redis.multi do
   redis.set('key', 'hi')
   @value = redis.get('key')
   redis.set('key', '2')
   @number = redis.incr('key')
end

p @value.value # 输出"hi"
p @number.value # 输出3

5.2.4 实践:自动完成

现在很多网站都有标签功能,用户可以给某个项目(如文章、图书等)添加标签,也可以通过标签查询项目。在很多时候,我们都希望在用户输入标签时网站可以自动帮助用户补全要输入的标签,如图5-1所示。

这样做一是可以节约用户的输入时间,二是在创建标签时可以起到规范标签的作用,避免用户输入标签时可能出现的拼写错误。

下面介绍两种在Redis中实现补全提示的方法,并会挑选一种用Ruby来实现。

第一种方法:为每个标签的每个前缀都使用一个集合类型键来存储该前缀对应的标签名。如“ruby”的所有前缀分别是“r”、“ru”和“rub”,我们为这3个前缀对应的集合类型键都加入元素“ruby”。

当有“ruby”和“redis”两个标签时Redis中存储的内容如图5-2所示,用户输入“r”时就可以通过读取键“prefix:r”来获知以“r”开头的标签有“ruby”和“redis”两个。

这时就可以将这两个标签提示给用户了。更进一步,我们还可以存储每个标签的访问量,使得我们可以利用SORT命令配合BY参数把最热门的标签排在前面。

第二种方法通过有序集合实现,该方法是由Redis的作者Salvatore Sanfilippo介绍的。

3.6 节介绍过有序集合类型有一个特性是当元素的分数一样时会按照元素值的字典顺序排序,利用这一特性只使用一个有序集合类型键就能实现标签的补全功能,准备过程如下。

(1)首先把每个标签名的所有前缀作为元素存入键中,分数均为0;

(2)将每个标签名后面都加上“*”符号并存入键中,分数也为0。

准备过后的存储情况如图5-3所示。

由于所有元素的分数都相同,所以该有序集合键中的项目相当于全部按照字典顺序排序(即图5-3所示的顺序)。这样当用户输入“r”时就可以按照如下流程获取要提示给用户的标签:

获取“r”的排名:ZRANK autocomplete r,在这里的返回值是0;

获取“r”之后的N个元素,如当N=100时:ZRANGE autocomplete 1 101。 N的取值与标签的平均长度和需要获得的标签数量有关,可以根据实际情况自由调整;

遍历返回的结果,找出其中以""结尾的且以“r”开头的元素。此时将“”去掉后就是我们需要的结果了。

下面我们写一个小程序来作为示例,程序启动时会从一个文本文件中读取所有标签列表,然后接收用户输入并返回相应的补全结果。

文本文件的样例内容如下:

我的中国心
我的中国话
你好吗
我和你
你一路走来
你从哪里来

当用户输入“我的”时程序会打印如下内容:

我的中国心
我的中国话

具体的实现方法是,首先我们定义一个函数来获得标签的前缀(包括标签加上星号):

# 获得标签的所有前缀
#
# @example
#  get_prefixes('word')
#   # => ['w', 'wo', 'wor', 'word*']
def get_prefixes(word)
 Array.new(word.length) do |i|
  if i == word.length - 1
   "#{word}*"
  else
   word[0..i]
  end
 end
end

接着我们加载redis-rb,并建立到Redis的连接:

require 'redis'
# 建立到默认地址和端口的Redis的连接
redis = Redis.new

为了保证可以重复运行此程序,我们需要删除之前建立的键以免影响本次的结果:

redis.del('autocomplete')
下面是准备阶段,程序从words.txt文件读取标签列表,并获得每个标签的前缀加入到有序集合键中:

argv = []
File.open('words.txt').each_line do |word|
  get_prefixes(word.chomp).each do |prefix|
   argv << [0, prefix]
  end
end
redis.zadd('autocomplete', argv)
redis-rb 的 zadd 函数支持两种方式的参数:当只加入一个元素时使用 redis.zadd(key, score, member),当同时加入多个元素时使用redis.zadd(key, [[score1, member1], [score2, member2], …])上面的代码使用的是后一种方式。

最后一步我们通过循环来接收用户的输入并查询对应的标签:

while prefix = gets.chomp do
  result = []
  if (rank = redis.zrank('autocomplete', prefix))
   # 存在以用户输入的内容为前缀的标签
   redis.zrange('autocomplete', rank + 1, rank + 100).each do |words|
    # 获得该前缀后的100个元素
    if words[-1] == '*' && prefix == words[0..prefix.length - 1]
     # 如果以"*"结尾并以用户输入的内容为前缀则加入结果中
     result << words[0..-2]
    end
   end
  end
  # 打印结果
  puts result
end
时间: 2024-10-28 17:43:40

《Redis入门指南》一5.2 Ruby与Redis的相关文章

《Redis入门指南(第2版)》一导读

前 言 Redis入门指南(第2版)Redis如今已经成为Web开发社区中最火热的内存数据库之一,而它的诞生距现在不过才4年.随着Web 2.0的蓬勃发展,网站数据快速增长,对高性能读写的需求也越来越多,再加上半结构化的数据比重逐渐变大,人们对早已被铺天盖地地运用着的关系数据库能否适应现今的存储需求产生了疑问.而Redis的迅猛发展,为这个领域注入了全新的思维. Redis凭借其全面的功能得到越来越多的公司的青睐,从初创企业到新浪微博这样拥有着几百台Redis服务器的大公司,都能看到Redis的

《Redis入门指南》一4.3 排序

4.3 排序 Redis入门指南 午后,宋老师正在批改学生们提交的程序,再过几天就会迎来第一次计算机全市联考.他在每个学生的程序代码末尾都用注释详细地做了批注--严谨的治学态度让他备受学生们的爱戴. 一个电话打来."小白的?"宋老师拿出手机,"博客最近怎么样了?"未及小白开口,他就抢先问道. 特别好!现在平均每天都有50多人访问我的博客.不过昨天我收到一个访客的邮件,他向我反映了一个问题:查看一个标签下的文章列表时文章不是按照时间顺序排列的,找起来很麻烦.我看了一下

《Redis入门指南》一第5章 实践

第5章 实践 Redis入门指南 小白把宋老师向自己讲解的知识总结成了一篇帖子发在了学校的网站上,引起了强烈的反响.很多同学希望宋老师能够再写一些关于Redis实践方面的教程,宋老师爽快地答应了. 在此之前我们进行的操作都是通过Redis的命令行客户端redis-cli进行的,并没有介绍实际编程时如何操作Redis.本章将会通过4个实例分别介绍Redis的PHP.Python.Ruby和 Node.js 客户端的使用方法,即使你不了解其中的某些语言,粗浅的阅读一下也能收获很多实践方面的技巧.

《Redis入门指南》一导读

前 言 Redis入门指南Redis如今已经成为Web开发社区中最火热的内存数据库之一,而它的诞生距现在不过才4年.随着Web 2.0的蓬勃发展,网站数据快速增长,对高性能读写的需求也越来越多,再加上半结构化的数据比重逐渐变大,人们对早已被铺天盖地地运用着的关系数据库能否适应现今的存储需求产生了疑问.而Redis的迅猛发展,为这个领域注入了全新的思维. Redis凭借其全面的功能得到越来越多的公司的青睐,从初创企业到新浪微博这样拥有着几百台Redis服务器的大公司,都能看到Redis的身影.Re

《Redis入门指南》一5.1 PHP与Redis

5.1 PHP与Redis Redis入门指南 Redis官方推荐的PHP客户端是Predis1和phpredis2.前者是完全使用PHP代码实现的原生客户端,而后者则是使用C语言编写的PHP扩展.在功能上两者区别并不大,就性能而言后者会更胜一筹.考虑到很多主机并未提供安装PHP扩展的权限,本节会以Predis为示例介绍如何在PHP中使用Redis. 虽然Predis的性能逊于phpredis,但是除非执行大量Redis命令,否则很难区分二者的性能.而且实际应用中执行Redis命令的开销更多在网

《Redis入门指南》一5.3 Python与Redis

5.3 Python与Redis Redis入门指南 Redis官方推荐的Python客户端是redis-py1. 5.3.1 安装 推荐使用pip install redis安装最新版本的redis-py,也可以使用easy_install:easy_install redis. 5.3.2 使用方法 首先需要引入redis-py: import redis 下面的代码将创建一个默认连接到地址127.0.0.1,端口6379的Redis连接: r = redis.StrictRedis() 也

《Redis入门指南》一4.1 事务

4.1 事务 Redis入门指南 傍晚时候,忙完了一天的教学工作,宋老师坐在办公室的电脑前开始为明天的课程做准备.尽管有着近5年的教学经验,可是宋老师依然习惯在备课时写一份简单的教案.正在网上查找资料时,在浏览器的历史记录里他突然看到了小白的博客.心想:不知道他的博客怎么样了? 于是宋老师点进了小白的博客,页面刚载入完他就被博客最下面的一行大得夸张的文字吸引了:"Powered by Redis".宋老师笑了笑,接着就看到了小白博客中最新的一篇文章: 标题: 使用Redis来存储微博中

《Redis入门指南》一4.4 消息通知

4.4 消息通知 Redis入门指南 凭着小白的用心经营,博客的访问量逐渐增多,甚至有了小白自己的粉丝.这不,小白刚收到一封来自粉丝的邮件,在邮件中那个粉丝强烈建议小白给博客加入邮件订阅功能,这样当小白发布新文章后订阅小白博客的用户就可以收到通知邮件了.在信的末尾,那个粉丝还着重强调了一下:"这个功能对不习惯使用RSS的用户很重要,希望能够加上!" 看过信后,小白心想:"是个好建议!不过话说回来,似乎他还没发现其实我的博客连RSS功能都没有." 邮件订阅功能太好实现

《Redis入门指南》一5.4 Node.js与Redis

5.4 Node.js与Redis Redis入门指南 Redis官方推荐的Node.js客户端是node_redis1. 5.4.1 安装 使用npm install redis命令安装最新版本的node_redis,目前版本是0.8.2. 5.4.2 使用方法 首先加载node_redis模块: var redis = require('redis'); 下面的代码将创建一个默认连接到地址127.0.0.1,端口6379的Redis连接: var client = redis.createC