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
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
AI によるインシデント初動調査の自動化を行う AI インシデントコマンダーを作った話
azukiazusa1
1
740
AWS re:Invent 2025参加 直前 Seattle-Tacoma Airport(SEA)におけるハードウェア紛失インシデントLT
tetutetu214
2
120
[KNOTS 2026登壇資料]AIで拡張‧交差する プロダクト開発のプロセス および携わるメンバーの役割
hisatake
0
290
OCaml 5でモダンな並列プログラミングを Enjoyしよう!
haochenx
0
140
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
200
Basic Architectures
denyspoltorak
0
680
AI時代の認知負荷との向き合い方
optfit
0
160
AI巻き込み型コードレビューのススメ
nealle
2
440
「ブロックテーマでは再現できない」は本当か?
inc2734
0
1k
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
200
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
600
要求定義・仕様記述・設計・検証の手引き - 理論から学ぶ明確で統一された成果物定義
orgachem
PRO
1
170
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
130
Site-Speed That Sticks
csswizardry
13
1.1k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.3k
SEO for Brand Visibility & Recognition
aleyda
0
4.2k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
0
1.1k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
0
3.4k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.4k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
1
1.3k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.6k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
270
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日星期⼀一