Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Redis Serach Introduction
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Jason Lee
November 28, 2011
Programming
13
760
Redis Serach Introduction
This is a Introduction for redis-search gem.
Jason Lee
November 28, 2011
Tweet
Share
More Decks by Jason Lee
See All by Jason Lee
Ruby China 背后的故事
huacnlee
25
3.7k
Ruby 入门第一课
huacnlee
1
170
How to collect content form Web
huacnlee
7
270
Other Decks in Programming
See All in Programming
MUSUBIXとは
nahisaho
0
130
CSC307 Lecture 04
javiergs
PRO
0
660
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
7
3.9k
AWS re:Invent 2025参加 直前 Seattle-Tacoma Airport(SEA)におけるハードウェア紛失インシデントLT
tetutetu214
2
110
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
450
AI時代の認知負荷との向き合い方
optfit
0
160
ぼくの開発環境2026
yuzneri
0
230
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
1
130
OSSとなったswift-buildで Xcodeのビルドを差し替えられるため 自分でXcodeを直せる時代になっている ダイアモンド問題編
yimajo
3
620
AI巻き込み型コードレビューのススメ
nealle
2
320
CSC307 Lecture 03
javiergs
PRO
1
490
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
380
Featured
See All Featured
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
370
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
140
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
93
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.7k
Why Our Code Smells
bkeepers
PRO
340
58k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.2k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
320
Rails Girls Zürich Keynote
gr2m
96
14k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Transcript
Rails App 运用 Redis 构建 高性能的实时搜索 李华顺 11年11月7日星期⼀一
Name: 李华顺 (Jason Lee) Twitter: @huacnlee Github: http://github.com/huacnlee 者也 淘宝
MED 11年11月7日星期⼀一
目前市面上的搜索引擎项目 11年11月7日星期⼀一
但我不讲它们! 11年11月7日星期⼀一
11年11月7日星期⼀一
Background • 做了者也(zheye.org)这个网站; • 需要实现类似 Quora 那样高效的搜索功能; • 采用 Ruby
on Rails 开发, MongoDB 数据库; • 中文的搜索,需要分词; • 需要逐字匹配搜索; 11年11月7日星期⼀一
11年11月7日星期⼀一
• 能够在键盘输入的瞬间响应搜索结果; • MongoDB 支持; • 不需要太复杂的查询,单个字段作为搜索条件; • 逐字匹配功能; •
分词、模糊匹配; • 实时更新; • 排序; 此搜索功能的需求 11年11月7日星期⼀一
为什么不用 Sphinx 或其他的开源项目 • 查询速度无法满足按键瞬间需要响应的 需求 • 对于 MongoDB 的,暂无现成的组件可用
• 需要逐字匹配搜索 • 实时更新索引 11年11月7日星期⼀一
起初的实现机制 set keys *关键词* mget class Ask after_create do key
= "quora:#{self.title.downcase}" $redis.set(key,{:id => self.id,:title => self.title, :type => self.type}) end before_destroy do $redis.del("quora:#{self.title_was.downcase}") end def search(text,limit = 10) words = RMMSeg.split(text) keys = $redis.keys("*#{words.collect(&:downcase).join("*")}*")[0,limit] result = $redis.mget(*keys) items = [] result.each do |r| items << JSON.parse(r) end items.sort { |b,a| a['type'] <=> b['type'] } return items end end 11年11月7日星期⼀一
问题 • 数据上了10万+会越来越慢 • 分词搜索只能按顺序输入的查询 • 无法排序 11年11月7日星期⼀一
改如何改进? 11年11月7日星期⼀一
SINTER SUNION 运用 Redis 的特性 Sets 关键词索引 实体数据 SADD SREM
Hashes HMGET HDEL HSET Sorted Sets 前缀匹配索引 ZADD ZRANK ZRANGE 11年11月7日星期⼀一
Redis-Search 的索引结构 11年11月7日星期⼀一
Ask { 'id' : 1, 'title' : 'Ruby on Rails
为什么室如此高效?' , 'score' : 4 } { 'id' : 2, 'title' : 'Ruby 编程入门应该看什么书籍?', 'score' : 20 } { 'id' : 3, 'title' : 'Ruby 和 Python 那个更好?' , 'score' : 13 } { 'id' : 4, 'title' : '做 Python 开发应该用什么开发工具比较好?', 'score' : 5 } 演示数据: Topic { 'id' : 1, 'name' : 'Ruby' , 'score' : 5 } { 'id' : 2, 'name' : 'Rails' , 'score' : 18 } { 'id' : 3, 'name' : 'Rubies', 'score' : 10 } { 'id' : 4, 'name' : 'Rake', 'score' : 4 } { 'id' : 5, 'name' : 'Python' , 'score' : 2 } prefix_index_enable = true 11年11月7日星期⼀一
前缀匹配索引 Sorted Sets 关键词索引 Sets topic:rails [2] ask:rails [1] topic:ruby
[1] ask:ruby [1,2,3] topic:rails [4] topic:rubies [5] ask:python [3,4] ask:什么 [1,2,4] ...... Score排序索引 ask:_score_:1 4 ask:_score_:2 20 ask:_score_:3 13 ask:_score_:4 5 topic:_score_:1 18 topic:_score_:2 10 topic:_score_:3 4 topic:_score_:4 2 ...... Sets 索引 1. r 2. ra 3. rai 4. rail 5. rails* 6. rak 7. rake* 8. ru 9. rub 10.rubi 11.rubie 12.rubies* 13.ruby* ‣ * 号项表示实际词 ‣ 自动排序存放 11年11月7日星期⼀一
索引实际数据 Topic topic:1 { 'id' : 1, 'name' : 'Ruby'
} topic:2 { 'id' : 2, 'name' : 'Rails' } topic:3 { 'id' : 3, 'name' : 'Rubies' } topic:4 { 'id' : 4, 'name' : 'Rake' } topic:5 { 'id' : 5, 'name' : 'Python' } Hashes Ask ask:1 { 'id' : 1, 'title' : 'Ruby on Rails 为什么如此高效?' } ask:2 { 'id' : 2, 'title' : 'Ruby 编程入门应该看什么书籍?' } ask:3 { 'id' : 3, 'title' : 'Ruby 和 Python 那个更好?' } ask:4 { 'id' : 4, 'title' : '做 Python 开发应该用什么开发工具比较好?' } 11年11月7日星期⼀一
前缀匹配搜索过程 r 1 [rails,rake,rubies,ruby] ru 8 [rubies,ruby] ruby 13 [ruby]
输入 坐标 得到从坐标 1 到 101 之间的前缀,并取出带 * 号的项 redis> ZRANGE 1 100+1 redis> SORT topic:rubies+ruby BY topic:_score_:* DESC LIMIT 0 10 [2,3,1,4] 返回到 redis-search [2,1] [1] redis> HMGET ask 2,3,1,4 结果 1. r 2. ra 3. rai 4. rail 5. rails* 6. rak 7. rake* 8. ru 9. rub 10. rubi 11. rubie 12. rubies* 13. ruby* redis> ZRANK r rub 9 redis> SUNIONSTORE topic:rubies+ruby topic:rubies topic:ruby 取关键词的并集 排序 { 'id' : 2, 'name' : 'Rails' , 'score' : 18 } { 'id' : 3, 'name' : 'Rubies', 'score' : 10 } { 'id' : 1, 'name' : 'Ruby' , 'score' : 5 } { 'id' : 4, 'name' : 'Rake', 'score' : 4 } http://antirez.com/post/autocomplete-with-redis.html 前缀算法索引来源: 11年11月7日星期⼀一
分词搜索过程 Ruby [ruby] [1,2,3] Ruby 什么 [ruby,什么] [1,2] Ruby 什么书籍
[ruby,什么,书籍] [2] 输入 分词得到 交集 (in Redis) redis> SINTERSTORE ask:ruby+什么+书籍 ask:ruby ask:什么 ask:书籍 redis> SORT ask:ruby+什么+书籍 BY ask:_score_:* DESC LIMIT 0 10 [2,3,1] 返回编号到 redis-search [2,1] [2] redis> HMGET ask 2,3,1 { 'id' : 2, 'title' : 'Ruby 编程入门应该看什么书籍?', 'score' : 20 } { 'id' : 3, 'title' : 'Ruby 和 Python 那个更好?' , 'score' : 13 } { 'id' : 1, 'title' : 'Ruby on Rails 为什么室如此高效?' , 'score' : 4 } 结果 11年11月7日星期⼀一
so... 11年11月7日星期⼀一
Redis-Search ActiveRecord 11年11月7日星期⼀一
Redis-Search 特性 • iMac 上面能够 100万+ 数据的搜索能够达到10ms/次 以内响 应速度; •
实时更新搜索索引; • 中文分词搜索 (rmmseg-cpp) • 前缀匹配搜索; • No-SQL - 无需查询原始数据库; • 根据汉语拼音搜索(chinese_pinyin); • ActiveRecord 和 Mongoid 支持; 11年11月7日星期⼀一
Redis-Search 的局限性 • 只能针对⼀一个字段搜索(后面会加入别名搜索功能); • 排序选项有限(目前只有⼀一个); • 附加条件只能是 =,不能 >
或 < ...; • 拼音搜索在某些同音字场景下面会有小出入; 11年11月7日星期⼀一
应用场景 • 文章搜索; • 搜索用户; • 国家,城市匹配; • 好友匹配; •
分类,Tag 匹配; • 其他名称匹配(如:店名,地址,品牌,书籍,电影,音 乐...) • 相关内容匹配; 11年11月7日星期⼀一
How to use it? 11年11月7日星期⼀一
gem 'redis','>= 2.1.1' gem 'chinese_pinyin', '0.4.1' gem 'rmmseg-cpp-huacnlee', '0.2.9' gem
'redis-namespace','~> 1.1.0' gem 'redis-search', '0.7.0' Gemfile shell> bundle install 安装 11年11月7日星期⼀一
config/initializers/redis_search.rb require "redis" require "redis-namespace" require "redis-search" redis = Redis.new(:host
=> "127.0.0.1",:port => "6379") redis.select(3) # 设置命名空间,防止和其他项目发生冲突 redis = Redis::Namespace.new("your_app_name:search", :redis => redis) Redis::Search.configure do |config| config.redis = redis # 前缀匹配搜索阀值,设置多少要看你需要前缀匹配的内容,最长的字数有多少,越短越好 config.complete_max_length = 100 # 是否开启拼音搜索 config.pinyin_match = true end 配置 11年11月7日星期⼀一
Model 配置 class User include Mongoid::Document include Redis::Search field :name
field :tagline field :email field :followers_count, :type => Integer, :default => 0 field :sex, :type => Integer, :default => 0 # 开启次 Model 的搜索索引 # title_field 用于搜索的字段 # prefix_index_enable 是否使用逐字匹配 # score_field 排序字段 # condition_fields 附加条件 # ext_fields 存入 Hash 的字段,因为 redis-search 不再查询原始数据库,所以如果 显示需要某些字段,请把它定义到这里 redis_search_index(:title_field => :name, :prefix_index_enable => true, :score_field => :followers_count, :condition_fields => [:sex] :ext_fields => [:email,:tagline]) end 11年11月7日星期⼀一
配置好以后,Redis-Search 将会在数据 Create, Update, Destroy 的时候自动更新 Redis 里面的索引,以及 Hash 数据,无需理
会更新的问题。 11年11月7日星期⼀一
查询 rails c> Redis::Search.complete('User', 'hua', :conditions => {:sex => 1},
:limit => 20) 前缀匹配搜索: 普通分词搜索: rails c> Redis::Search.query('Ask', 'Ruby敏捷开发', :conditions => {:state => 1}, :limit => 20) 11年11月7日星期⼀一
http://github.com/huacnlee/redis-search 项目地址 11年11月7日星期⼀一
Thanks 11年11月7日星期⼀一