Module: Redis::Search
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/redis/search/base.rb,
lib/redis/search/index.rb,
lib/redis/search/config.rb,
lib/redis/search/finder.rb,
lib/redis/search/railtie.rb
Defined Under Namespace
Modules: ClassMethods Classes: Config, Index, Railtie
Class Attribute Summary collapse
-
.config ⇒ Object
Returns the value of attribute config.
-
.indexed_models ⇒ Object
Returns the value of attribute indexed_models.
Class Method Summary collapse
-
.complete(type, w, options = {}) ⇒ Object
Use for short title search, this method is search by chars, for example Tag, User, Category …
- .configure {|@config ||= Config.new| ... } ⇒ Object
-
.query(type, text, options = {}) ⇒ Object
Search items, this will split words by Libmmseg.
-
.split(text) ⇒ Object
use rmmseg to split words.
Class Attribute Details
.config ⇒ Object
Returns the value of attribute config.
5 6 7 |
# File 'lib/redis/search/config.rb', line 5 def config @config end |
.indexed_models ⇒ Object
Returns the value of attribute indexed_models.
5 6 7 |
# File 'lib/redis/search/config.rb', line 5 def indexed_models @indexed_models end |
Class Method Details
.complete(type, w, options = {}) ⇒ Object
Use for short title search, this method is search by chars, for example Tag, User, Category …
h3. params:
type model name
w search char
:limit result limit
h3. usage:
-
Redis::Search.complete(“Tag”,“r”) => [“Ruby”,“Rails”, “REST”, “Redis”, “Redmine”]
-
Redis::Search.complete(“Tag”,“re”) => [“Redis”, “Redmine”]
-
Redis::Search.complete(“Tag”,“red”) => [“Redis”, “Redmine”]
-
Redis::Search.complete(“Tag”,“redi”) => [“Redis”]
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/redis/search/finder.rb', line 21 def complete(type, w, = {}) limit = [:limit] || 10 conditions = [:conditions] || [] return [] if (w.blank? && conditions.blank?) || type.blank? prefix_matchs = [] # This is not random, try to get replies < MTU size rangelen = self.config.complete_max_length prefix = w.downcase key = self.mk_complete_key(type) if start = self.config.redis.zrank(key,prefix) count = limit max_range = start + (rangelen * limit) - 1 range = self.config.redis.zrange(key,start,max_range) while prefix_matchs.length <= count start += rangelen break if !range || range.length == 0 range.each do |entry| minlen = [entry.length,prefix.length].min if entry[0...minlen] != prefix[0...minlen] count = prefix_matchs.count break end if entry[-1..-1] == "*" && prefix_matchs.length != count prefix_matchs << entry[0...-1] end end range = range[start..max_range] end end prefix_matchs.uniq! # 组合 words 的特别 key 名 words = prefix_matchs.collect { |w| self.mk_sets_key(type,w) } # 组合特别 key ,但这里不会像 query 那样放入 words, 因为在 complete 里面 words 是用 union 取的,condition_keys 和 words 应该取交集 condition_keys = [] if !conditions.blank? conditions = conditions[0] if conditions.is_a?(Array) conditions.keys.each do |c| condition_keys << self.mk_condition_key(type,c,conditions[c]) end end # 按词语搜索 temp_store_key = "tmpsunionstore:#{words.join("+")}" if words.length > 1 if !self.config.redis.exists(temp_store_key) # 将多个词语组合对比,得到并集,并存入临时区域 self.config.redis.sunionstore(temp_store_key,*words) # 将临时搜索设为1天后自动清除 self.config.redis.expire(temp_store_key,86400) end # 根据需要的数量取出 ids else temp_store_key = words.first end # 如果有条件,这里再次组合一下 if !condition_keys.blank? condition_keys << temp_store_key if !words.blank? temp_store_key = "tmpsinterstore:#{condition_keys.join('+')}" if !self.config.redis.exists(temp_store_key) self.config.redis.sinterstore(temp_store_key,*condition_keys) self.config.redis.expire(temp_store_key,86400) end end ids = self.config.redis.sort(temp_store_key, :limit => [0,limit], :by => self.mk_score_key(type,"*"), :order => "desc") return [] if ids.blank? self.hmget(type,ids) end |
.configure {|@config ||= Config.new| ... } ⇒ Object
7 8 9 10 11 12 13 14 15 |
# File 'lib/redis/search/config.rb', line 7 def configure yield @config ||= Config.new if not @config.disable_rmmseg require "rmmseg" # loading RMMSeg chinese word dicts. RMMSeg::Dictionary.load_dictionaries end end |
.query(type, text, options = {}) ⇒ Object
Search items, this will split words by Libmmseg
h3. params:
type model name
text search text
:limit result limit
h3. usage:
-
Redis::Search.query(“Tag”,“Ruby vs Python”)
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/redis/search/finder.rb', line 107 def query(type, text, = {}) tm = Time.now result = [] limit = [:limit] || 10 sort_field = [:sort_field] || "id" conditions = [:conditions] || [] # 如果搜索文本和查询条件均没有,那就直接返回 [] return result if text.strip.blank? && conditions.blank? words = self.split(text) words = words.collect { |w| self.mk_sets_key(type,w) } condition_keys = [] if !conditions.blank? conditions = conditions[0] if conditions.is_a?(Array) conditions.keys.each do |c| condition_keys << self.mk_condition_key(type,c,conditions[c]) end # 将条件的 key 放入关键词搜索集合内,用于 sinterstore 搜索 words += condition_keys end return result if words.blank? temp_store_key = "tmpinterstore:#{words.join("+")}" if words.length > 1 if !self.config.redis.exists(temp_store_key) self.config.redis.pipelined do # 将多个词语组合对比,得到交集,并存入临时区域 self.config.redis.sinterstore(temp_store_key,*words) # 将临时搜索设为1天后自动清除 self.config.redis.expire(temp_store_key,86400) # 拼音搜索 if self.config. = self.(text) = .collect { |w| self.mk_sets_key(type,w) } += condition_keys temp_sunion_key = "tmpsunionstore:#{words.join("+")}" = "tmpinterstore:#{.join("+")}" # 找出拼音的 self.config.redis.sinterstore(,*) # 合并中文和拼音的搜索结果 self.config.redis.sunionstore(temp_sunion_key,*[temp_store_key,]) # 将临时搜索设为1天后自动清除 self.config.redis.expire(,86400) self.config.redis.expire(temp_sunion_key,86400) end temp_store_key = temp_sunion_key end end else temp_store_key = words.first end # 根据需要的数量取出 ids ids = self.config.redis.sort(temp_store_key, :limit => [0,limit], :by => self.mk_score_key(type,"*"), :order => "desc") result = self.hmget(type,ids, :sort_field => sort_field) self.info("{#{type} : \"#{text}\"} | Time spend: #{Time.now - tm}s") result end |
.split(text) ⇒ Object
use rmmseg to split words
6 7 8 |
# File 'lib/redis/search/finder.rb', line 6 def split(text) _split(text) end |