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
Jason Lee
November 28, 2011
Programming
13
730
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.6k
Ruby 入门第一课
huacnlee
1
140
How to collect content form Web
huacnlee
7
260
Other Decks in Programming
See All in Programming
月刊 競技プログラミングをお仕事に役立てるには
terryu16
1
1.2k
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
390
AHC041解説
terryu16
0
390
ESLintプラグインを使用してCDKのセオリーを適用する
yamanashi_ren01
2
240
「とりあえず動く」コードはよい、「読みやすい」コードはもっとよい / Code that 'just works' is good, but code that is 'readable' is even better.
mkmk884
6
1.4k
Beyond ORM
77web
11
1.6k
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
870
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
1.4k
毎日13時間もかかるバッチ処理をたった3日で60%短縮するためにやったこと
sho_ssk_
1
550
テストコード書いてみませんか?
onopon
2
340
Jaspr Dart Web Framework 박제창 @Devfest 2024
itsmedreamwalker
0
150
ChatGPT とつくる PHP で OS 実装
memory1994
PRO
3
190
Featured
See All Featured
Practical Orchestrator
shlominoach
186
10k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.2k
What's in a price? How to price your products and services
michaelherold
244
12k
GitHub's CSS Performance
jonrohan
1030
460k
Measuring & Analyzing Core Web Vitals
bluesmoon
5
210
How to Ace a Technical Interview
jacobian
276
23k
For a Future-Friendly Web
brad_frost
176
9.5k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.1k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
45
2.3k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.4k
Scaling GitHub
holman
459
140k
The Pragmatic Product Professional
lauravandoore
32
6.4k
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日星期⼀一