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
720
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
130
How to collect content form Web
huacnlee
7
250
Other Decks in Programming
See All in Programming
as(型アサーション)を書く前にできること
marokanatani
10
2.7k
Laravel や Symfony で手っ取り早く OpenAPI のドキュメントを作成する
azuki
2
120
Less waste, more joy, and a lot more green: How Quarkus makes Java better
hollycummins
0
100
Duckdb-Wasmでローカルダッシュボードを作ってみた
nkforwork
0
130
Webの技術スタックで マルチプラットフォームアプリ開発を可能にするElixirDesktopの紹介
thehaigo
2
1k
.NET のための通信フレームワーク MagicOnion 入門 / Introduction to MagicOnion
mayuki
1
1.6k
Jakarta EE meets AI
ivargrimstad
0
180
카카오페이는 어떻게 수천만 결제를 처리할까? 우아한 결제 분산락 노하우
kakao
PRO
0
110
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
1.9k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
110
Amazon Qを使ってIaCを触ろう!
maruto
0
410
LLM生成文章の精度評価自動化とプロンプトチューニングの効率化について
layerx
PRO
2
190
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
169
14k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
890
How to train your dragon (web standard)
notwaldorf
88
5.7k
KATA
mclloyd
29
14k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
Embracing the Ebb and Flow
colly
84
4.5k
Done Done
chrislema
181
16k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
Designing for Performance
lara
604
68k
Into the Great Unknown - MozCon
thekraken
32
1.5k
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日星期⼀一