redis-search 0.9.7 → 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 715f373324e8d649a86d38d05ce25e044b4ebacc
4
- data.tar.gz: bc32f91272a550a62f697366df1c807d2b7c58c2
3
+ metadata.gz: c3db9e3cf11d6d82edb9366ec887db853a684468
4
+ data.tar.gz: 349c2ad7333803b7f868cabd5ee4053f216b9e14
5
5
  SHA512:
6
- metadata.gz: dc3272074ff70fd82998bd46d7b566a6072ceb7c3820411e8169386f395cecf98896100934edae3e15e1bf50406a7e3556de1c15f0f32e402deb01d548f882ad
7
- data.tar.gz: c115f7733556b42db81f707d0a857697e9881cf78b5e7dabbd3b2d67dd3d72d953e84a4b04a98af23190aae3546287abaf9c8902f36c93b0a19ec82d0a5385fe
6
+ metadata.gz: e1d2dcf8826e6c4e0e3a9414fdc0a8f1b11fc9d0cf024f5c6d5ab27e56e7da3c436f5ab20d1c487f6e2feab09d24462de24cee03209ecccf5c4ce7c51a56d423
7
+ data.tar.gz: 9389c3f640c4ff76719507d681fb0d8ba4bc24cb7d36544617c76c4d209709121ec87e052e2ae4e6d52ecbb9cba3e09b212aafc1fa07e025c1dbc0a840dffbf1
data/README.md CHANGED
@@ -4,17 +4,10 @@ High performance real-time search (Support Chinese), index in Redis for Rails ap
4
4
 
5
5
  [中文介绍和使用说明](https://github.com/huacnlee/redis-search/wiki/Usage-in-Chinese)
6
6
 
7
- ## Demo
8
-
9
- ![](http://l.ruby-china.org/photo/34368688ee1c1928c2841eb2f41306ec.png)
10
-
11
- You can try the search feature in [`IMAX.im`](http://imax.im) | [`shu.im`](http://shu.im)
12
-
13
- And there is an [Example App](https://github.com/huacnlee/redis-search-example) to show you how to use redis-search.
14
-
15
7
  ## Master Status
16
8
 
17
- [![CI Status](https://secure.travis-ci.org/huacnlee/redis-search.png)](http://travis-ci.org/huacnlee/redis-search)
9
+ [![Gem Version](https://badge.fury.io/rb/redis-search.svg)](https://badge.fury.io/rb/redis-search) [![CI Status](https://secure.travis-ci.org/huacnlee/redis-search.svg)](http://travis-ci.org/huacnlee/redis-search) [![CodeCov](https://codecov.io/gh/huacnlee/redis-search/branch/master/graph/badge.svg)](https://codecov.io/gh/huacnlee/redis-search)
10
+
18
11
 
19
12
  ## Features
20
13
 
@@ -34,99 +27,87 @@ And there is an [Example App](https://github.com/huacnlee/redis-search-example)
34
27
 
35
28
  ## Install
36
29
 
37
- 1. In Rails application Gemfile
38
-
39
- ```ruby
40
- gem 'ruby-pinyin', '0.3.0'
41
- gem 'redis-search', '0.9.6'
42
- ```
30
+ ```ruby
31
+ gem 'redis-search'
32
+ ```
43
33
 
44
- ```bash
45
- $ bundle install
46
- ```
34
+ ```bash
35
+ $ bundle install
36
+ ```
47
37
 
48
38
  ## Configure
49
39
 
50
- * Create file in: config/initializers/redis_search.rb
51
-
52
- ```ruby
53
- require "redis"
54
- require "redis-namespace"
55
- require "redis-search"
56
- # don't forget change namespace
57
- redis = Redis.new(:host => "127.0.0.1",:port => "6379")
58
- # We suggest you use a special db in Redis, when you need to clear all data, you can use flushdb command to clear them.
59
- redis.select(3)
60
- # Give a special namespace as prefix for Redis key, when your have more than one project used redis-search, this config will make them work fine.
61
- redis = Redis::Namespace.new("your_app_name:redis_search", :redis => redis)
62
- Redis::Search.configure do |config|
63
- config.redis = redis
64
- config.complete_max_length = 100
65
- config.pinyin_match = true
66
- # use rmmseg, true to disable it, it can save memroy
67
- config.disable_rmmseg = false
68
- end
69
- ```
40
+ * Create file in: config/initializers/redis-search.rb
41
+
42
+ ```ruby
43
+ require "redis"
44
+ require "redis-namespace"
45
+ require "redis-search"
46
+
47
+ # don't forget change namespace
48
+ redis = Redis.new(host: '127.0.0.1', port: '6379')
49
+ # We suggest you use a special db in Redis, when you need to clear all data, you can use `flushdb` command to cleanup.
50
+ redis.select(3)
51
+ # Give a special namespace as prefix for Redis key, when your have more than one project used redis-search, this config will make them work fine.
52
+ redis = Redis::Namespace.new("your_app_name:redis_search", redis: redis)
53
+ Redis::Search.configure do |config|
54
+ config.redis = redis
55
+ config.complete_max_length = 100
56
+ config.pinyin_match = true
57
+ # use rmmseg, true to disable it, it can save memroy
58
+ config.disable_rmmseg = false
59
+ end
60
+ ```
70
61
 
71
62
  ## Usage
72
63
 
73
- * Bind Redis::Search callback event, it will to rebuild search indices when data create or update.
74
-
75
- ```ruby
76
- class Post
77
- include Mongoid::Document
78
- include Redis::Search
79
-
80
- field :title
81
- field :body
82
- field :hits
83
-
84
- belongs_to :user
85
- belongs_to :category
86
-
87
- redis_search_index(:title_field => :title,
88
- :score_field => :hits,
89
- :condition_fields => [:user_id, :category_id],
90
- :ext_fields => [:category_name])
91
-
92
- def category_name
93
- self.category.name
94
- end
95
- end
96
- ```
97
-
98
- ```ruby
99
- class User
100
- include Mongoid::Document
101
- include Redis::Search
102
-
103
- field :name
104
- field :alias_names, :type => Array
105
- field :tagline
106
- field :email
107
- field :followers_count
108
-
109
- redis_search_index(:title_field => :name,
110
- :alias_field => :alias_names,
111
- :prefix_index_enable => true,
112
- :score_field => :followers_count,
113
- :ext_fields => [:email,:tagline])
114
- end
115
- ```
116
-
117
- ```ruby
118
- class SearchController < ApplicationController
119
- # GET /searchs?q=title
120
- def index
121
- Redis::Search.query("Post", params[:q], :conditions => {:user_id => 12})
122
- end
123
-
124
- # GET /search_users?q=j
125
- def search_users
126
- Redis::Search.complete("Post", params[:q], :conditions => {:user_id => 12, :category_id => 4})
127
- end
128
- end
129
- ```
64
+ * Bind `Redis::Search` callback event, it will to rebuild search indices when data create or update.
65
+
66
+ ```ruby
67
+ class Post < ActiveRecord::Base
68
+ include Redis::Search
69
+
70
+ belongs_to :user
71
+ belongs_to :category
72
+
73
+ redis_search_index(title_field: :title,
74
+ score_field: :hits,
75
+ condition_fields: [:user_id, :category_id],
76
+ ext_fields: [:category_name])
77
+
78
+ def category_name
79
+ self.category.name
80
+ end
81
+ end
82
+ ```
83
+
84
+ ```ruby
85
+ class User < ActiveRecord::Base
86
+ include Redis::Search
87
+
88
+ serialize :alias_names, Array
89
+
90
+ redis_search_index(title_field: :name,
91
+ alias_field: :alias_names,
92
+ prefix_index_enable: true,
93
+ score_field: :followers_count,
94
+ ext_fields: [:email, :tagline])
95
+ end
96
+ ```
97
+
98
+ ```ruby
99
+ class SearchController < ApplicationController
100
+ # GET /searchs?q=title
101
+ def index
102
+ Redis::Search.query("Post", params[:q], conditions: { user_id: 12 })
103
+ end
104
+
105
+ # GET /search_users?q=j
106
+ def search_users
107
+ Redis::Search.complete("Post", params[:q], conditions: { user_id: 12, category_id: 4 })
108
+ end
109
+ end
110
+ ```
130
111
 
131
112
  ## Index data to Redis
132
113
 
@@ -135,13 +116,13 @@ And there is an [Example App](https://github.com/huacnlee/redis-search-example)
135
116
  Redis-Search index data to Redis from your model (pass name as CLASS environment variable).
136
117
 
137
118
  ```bash
138
- $ rake redis_search:index:model CLASS='MyModel'
119
+ $ rake redis_search:index:model CLASS='User'
139
120
  ```
140
121
 
141
122
  Customize the batch size:
142
123
 
143
124
  ```bash
144
- $ rake redis_search:index:model CLASS='MyModel' BATCH=100
125
+ $ rake redis_search:index:model CLASS='User' BATCH=100
145
126
  ```
146
127
 
147
128
  ### All Models
@@ -170,6 +151,15 @@ There is my performance test result.
170
151
 
171
152
  * [https://gist.github.com/1150933](https://gist.github.com/1150933)
172
153
 
154
+ ## Demo
155
+
156
+ ![](http://l.ruby-china.org/photo/34368688ee1c1928c2841eb2f41306ec.png)
157
+
158
+ Projects used redis-search:
159
+
160
+ - [redis-search-example](https://github.com/huacnlee/redis-search-example) - An example for show you how to use redis-search.
161
+ - [IMAX.im](https://github.com/huacnlee/imax.im)
162
+
173
163
  ## License
174
164
 
175
165
  * MIT
@@ -1,6 +1,6 @@
1
- # coding: utf-8
2
- require "redis/search/base"
3
- require "redis/search/finder"
4
- require "redis/search/index"
5
- require "redis/search/config"
6
- require 'redis/search/railtie' if defined?(Rails)
1
+ require 'redis-search/base'
2
+ require 'redis-search/finder'
3
+ require 'redis-search/index'
4
+ require 'redis-search/config'
5
+ require 'redis-search/version'
6
+ require 'redis-search/railtie' if defined?(Rails)
@@ -1,9 +1,9 @@
1
- # coding: utf-8
2
1
  class Redis
2
+ # nodoc
3
3
  module Search
4
4
  autoload :PinYin, 'ruby-pinyin'
5
5
 
6
- extend ::ActiveSupport::Concern
6
+ extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
9
  cattr_reader :redis_search_options
@@ -22,28 +22,28 @@ class Redis
22
22
  end
23
23
 
24
24
  def redis_search_alias_value(field)
25
- return [] if field.blank? || field == "_was".freeze
26
- val = (instance_eval("self.#{field}") || "".freeze).clone
27
- return [] if !val.class.in?([String,Array])
28
- if val.is_a?(String)
29
- val = val.to_s.split(",")
30
- end
25
+ return [] if field.blank? || field == '_was'.freeze
26
+ val = (instance_eval("self.#{field}") || ''.freeze).clone
27
+ return [] unless val.class.in?([String, Array])
28
+ val = val.to_s.split(',') if val.is_a?(String)
31
29
  val
32
30
  end
33
31
 
34
32
  # Rebuild search index with create
35
33
  def redis_search_index_create
36
- s = Search::Index.new(title: self.send(self.redis_search_options[:title_field]),
37
- aliases: self.redis_search_alias_value(self.redis_search_options[:alias_field]),
38
- id: self.id,
39
- exts: self.redis_search_fields_to_hash(self.redis_search_options[:ext_fields]),
40
- type: self.redis_search_options[:class_name] || self.class.name,
41
- condition_fields: self.redis_search_options[:condition_fields],
42
- score: self.send(self.redis_search_options[:score_field]).to_i,
43
- prefix_index_enable: self.redis_search_options[:prefix_index_enable])
34
+ opts = {
35
+ title: send(redis_search_options[:title_field]),
36
+ aliases: redis_search_alias_value(redis_search_options[:alias_field]),
37
+ id: id,
38
+ exts: redis_search_fields_to_hash(redis_search_options[:ext_fields]),
39
+ type: redis_search_options[:class_name] || self.class.name,
40
+ condition_fields: redis_search_options[:condition_fields],
41
+ score: send(redis_search_options[:score_field]).to_i,
42
+ prefix_index_enable: redis_search_options[:prefix_index_enable]
43
+ }
44
+
45
+ s = Search::Index.new(opts)
44
46
  s.save
45
- # release s
46
- s = nil
47
47
  true
48
48
  end
49
49
 
@@ -51,15 +51,14 @@ class Redis
51
51
  titles.uniq!
52
52
  titles.each do |title|
53
53
  next if title.blank?
54
- Search::Index.remove(id: self.id, title: title, type: self.class.name)
54
+ Search::Index.remove(id: id, title: title, type: self.class.name)
55
55
  end
56
56
  true
57
57
  end
58
58
 
59
59
  def redis_search_index_before_destroy
60
- titles = []
61
- titles = redis_search_alias_value(self.redis_search_options[:alias_field])
62
- titles << self.send(self.redis_search_options[:title_field])
60
+ titles = redis_search_alias_value(redis_search_options[:alias_field])
61
+ titles << send(redis_search_options[:title_field])
63
62
 
64
63
  redis_search_index_delete(titles)
65
64
  true
@@ -67,10 +66,10 @@ class Redis
67
66
 
68
67
  def redis_search_index_need_reindex
69
68
  index_fields_changed = false
70
- self.redis_search_options[:ext_fields].each do |f|
71
- next if f.to_s == "id".freeze
69
+ redis_search_options[:ext_fields].each do |f|
70
+ next if f.to_s == 'id'.freeze
72
71
  field_method = "#{f}_changed?"
73
- if self.methods.index(field_method.to_sym) == nil
72
+ if methods.index(field_method.to_sym).nil?
74
73
  Redis::Search.warn("#{self.class.name} model reindex on update need #{field_method} method.")
75
74
  next
76
75
  end
@@ -79,24 +78,24 @@ class Redis
79
78
  end
80
79
 
81
80
  begin
82
- if self.send("#{self.redis_search_options[:title_field]}_changed?")
81
+ if send("#{redis_search_options[:title_field]}_changed?")
83
82
  index_fields_changed = true
84
83
  end
85
84
 
86
- if self.send(self.redis_search_options[:alias_field]) || self.send("#{self.redis_search_options[:title_field]}_changed?")
85
+ if send(redis_search_options[:alias_field]) ||
86
+ send("#{redis_search_options[:title_field]}_changed?")
87
87
  index_fields_changed = true
88
88
  end
89
89
  rescue
90
90
  end
91
91
 
92
- return index_fields_changed
92
+ index_fields_changed
93
93
  end
94
94
 
95
95
  def redis_search_index_after_update
96
- if self.redis_search_index_need_reindex
97
- titles = []
98
- titles = redis_search_alias_value("#{self.redis_search_options[:alias_field]}_was")
99
- titles << self.send("#{self.redis_search_options[:title_field]}_was")
96
+ if redis_search_index_need_reindex
97
+ titles = redis_search_alias_value("#{redis_search_options[:alias_field]}_was")
98
+ titles << send("#{redis_search_options[:title_field]}_was")
100
99
  redis_search_index_delete(titles)
101
100
  end
102
101
 
@@ -104,8 +103,8 @@ class Redis
104
103
  end
105
104
 
106
105
  def redis_search_index_after_save
107
- if self.redis_search_index_need_reindex || self.new_record?
108
- self.redis_search_index_create
106
+ if redis_search_index_need_reindex || new_record?
107
+ redis_search_index_create
109
108
  end
110
109
  true
111
110
  end
@@ -134,32 +133,32 @@ class Redis
134
133
  opts[:ext_fields] += opts[:condition_fields] if opts[:condition_fields].is_a?(Array)
135
134
 
136
135
  # store Model name to indexed_models for Rake tasks
137
- Search.indexed_models = [] if Search.indexed_models == nil
136
+ Search.indexed_models = [] if Search.indexed_models.nil?
138
137
  Search.indexed_models << self
139
138
 
140
- class_variable_set("@@redis_search_options".freeze, opts)
139
+ class_variable_set('@@redis_search_options'.freeze, opts)
141
140
  end
142
141
 
143
142
  def redis_search_index_batch_create(batch_size = 1000, progressbar = false)
144
143
  count = 0
145
- if self.ancestors.collect { |klass| klass.to_s }.include?("ActiveRecord::Base".freeze)
146
- find_in_batches(:batch_size => batch_size) do |items|
144
+ if ancestors.collect(&:to_s).include?('ActiveRecord::Base'.freeze)
145
+ find_in_batches(batch_size: batch_size) do |items|
147
146
  items.each do |item|
148
147
  item.redis_search_index_create
149
148
  count += 1
150
- print "." if progressbar
149
+ print '.' if progressbar
151
150
  end
152
151
  end
153
- elsif self.included_modules.collect { |m| m.to_s }.include?("Mongoid::Document".freeze)
152
+ elsif included_modules.collect(&:to_s).include?('Mongoid::Document'.freeze)
154
153
  all.each_slice(batch_size) do |items|
155
154
  items.each do |item|
156
155
  item.redis_search_index_create
157
156
  count += 1
158
- print "." if progressbar
157
+ print '.' if progressbar
159
158
  end
160
159
  end
161
160
  else
162
- puts "skiped, not support this ORM in current."
161
+ puts 'skiped, not support this ORM in current.'
163
162
  end
164
163
 
165
164
  count
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  class Redis
3
2
  module Search
4
3
  class << self
@@ -7,8 +6,8 @@ class Redis
7
6
  def configure
8
7
  yield @config ||= Config.new
9
8
 
10
- if not @config.disable_rmmseg
11
- require "rmmseg"
9
+ unless @config.disable_rmmseg
10
+ require 'rmmseg'
12
11
  # loading RMMSeg chinese word dicts.
13
12
  RMMSeg::Dictionary.load_dictionaries
14
13
  end
@@ -13,7 +13,9 @@ class Redis
13
13
  # type model name
14
14
  # w search char
15
15
  # :limit result limit
16
+ #
16
17
  # h3. usage:
18
+ #
17
19
  # * Redis::Search.complete("Tag","r") => ["Ruby","Rails", "REST", "Redis", "Redmine"]
18
20
  # * Redis::Search.complete("Tag","re") => ["Redis", "Redmine"]
19
21
  # * Redis::Search.complete("Tag","red") => ["Redis", "Redmine"]
@@ -25,24 +27,24 @@ class Redis
25
27
 
26
28
  prefix_matchs = []
27
29
  # This is not random, try to get replies < MTU size
28
- rangelen = self.config.complete_max_length
30
+ rangelen = config.complete_max_length
29
31
  prefix = w.downcase
30
- key = self.mk_complete_key(type)
32
+ key = mk_complete_key(type)
31
33
 
32
- if start = self.config.redis.zrank(key,prefix)
34
+ if start = config.redis.zrank(key, prefix)
33
35
  count = limit
34
36
  max_range = start + (rangelen * limit) - 1
35
- range = self.config.redis.zrange(key,start,max_range)
37
+ range = config.redis.zrange(key, start, max_range)
36
38
  while prefix_matchs.length <= count
37
39
  start += rangelen
38
- break if !range || range.length == 0
40
+ break if !range || range.empty?
39
41
  range.each do |entry|
40
- minlen = [entry.length,prefix.length].min
42
+ minlen = [entry.length, prefix.length].min
41
43
  if entry[0...minlen] != prefix[0...minlen]
42
44
  count = prefix_matchs.count
43
45
  break
44
46
  end
45
- if entry[-1..-1] == "*" && prefix_matchs.length != count
47
+ if entry[-1..-1] == '*' && prefix_matchs.length != count
46
48
  prefix_matchs << entry[0...-1]
47
49
  end
48
50
  end
@@ -53,25 +55,25 @@ class Redis
53
55
  prefix_matchs.uniq!
54
56
 
55
57
  # 组合 words 的特别 key 名
56
- words = prefix_matchs.collect { |w| self.mk_sets_key(type,w) }
58
+ words = prefix_matchs.collect { |w| mk_sets_key(type, w) }
57
59
 
58
60
  # 组合特别 key ,但这里不会像 query 那样放入 words, 因为在 complete 里面 words 是用 union 取的,condition_keys 和 words 应该取交集
59
61
  condition_keys = []
60
- if !conditions.blank?
62
+ unless conditions.blank?
61
63
  conditions = conditions[0] if conditions.is_a?(Array)
62
64
  conditions.keys.each do |c|
63
- condition_keys << self.mk_condition_key(type,c,conditions[c])
65
+ condition_keys << mk_condition_key(type, c, conditions[c])
64
66
  end
65
67
  end
66
68
 
67
69
  # 按词语搜索
68
- temp_store_key = "tmpsunionstore:#{words.join("+")}"
70
+ temp_store_key = "tmpsunionstore:#{words.join('+')}"
69
71
  if words.length > 1
70
- if !self.config.redis.exists(temp_store_key)
72
+ unless config.redis.exists(temp_store_key)
71
73
  # 将多个词语组合对比,得到并集,并存入临时区域
72
- self.config.redis.sunionstore(temp_store_key,*words)
74
+ config.redis.sunionstore(temp_store_key, *words)
73
75
  # 将临时搜索设为1天后自动清除
74
- self.config.redis.expire(temp_store_key,86400)
76
+ config.redis.expire(temp_store_key, 86_400)
75
77
  end
76
78
  # 根据需要的数量取出 ids
77
79
  else
@@ -79,21 +81,21 @@ class Redis
79
81
  end
80
82
 
81
83
  # 如果有条件,这里再次组合一下
82
- if !condition_keys.blank?
83
- condition_keys << temp_store_key if !words.blank?
84
+ unless condition_keys.blank?
85
+ condition_keys << temp_store_key unless words.blank?
84
86
  temp_store_key = "tmpsinterstore:#{condition_keys.join('+')}"
85
- if !self.config.redis.exists(temp_store_key)
86
- self.config.redis.sinterstore(temp_store_key,*condition_keys)
87
- self.config.redis.expire(temp_store_key,86400)
87
+ unless config.redis.exists(temp_store_key)
88
+ config.redis.sinterstore(temp_store_key, *condition_keys)
89
+ config.redis.expire(temp_store_key, 86_400)
88
90
  end
89
91
  end
90
92
 
91
- ids = self.config.redis.sort(temp_store_key,
92
- limit: [0,limit],
93
- by: self.mk_score_key(type,"*"),
94
- order: "desc")
93
+ ids = config.redis.sort(temp_store_key,
94
+ limit: [0, limit],
95
+ by: mk_score_key(type, '*'),
96
+ order: 'desc')
95
97
  return [] if ids.blank?
96
- self.hmget(type,ids)
98
+ hmget(type, ids)
97
99
  end
98
100
 
99
101
  # Search items, this will split words by Libmmseg
@@ -102,26 +104,28 @@ class Redis
102
104
  # type model name
103
105
  # text search text
104
106
  # :limit result limit
107
+ #
105
108
  # h3. usage:
106
109
  # * Redis::Search.query("Tag","Ruby vs Python")
110
+ #
107
111
  def query(type, text, options = {})
108
112
  tm = Time.now
109
113
  result = []
110
114
  limit = options[:limit] || 10
111
- sort_field = options[:sort_field] || "id"
115
+ sort_field = options[:sort_field] || 'id'
112
116
  conditions = options[:conditions] || []
113
117
 
114
118
  # 如果搜索文本和查询条件均没有,那就直接返回 []
115
119
  return result if text.strip.blank? && conditions.blank?
116
120
 
117
- words = self.split(text)
118
- words = words.collect { |w| self.mk_sets_key(type,w) }
121
+ words = split(text)
122
+ words = words.collect { |w| mk_sets_key(type, w) }
119
123
 
120
124
  condition_keys = []
121
- if !conditions.blank?
125
+ unless conditions.blank?
122
126
  conditions = conditions[0] if conditions.is_a?(Array)
123
127
  conditions.keys.each do |c|
124
- condition_keys << self.mk_condition_key(type,c,conditions[c])
128
+ condition_keys << mk_condition_key(type, c, conditions[c])
125
129
  end
126
130
  # 将条件的 key 放入关键词搜索集合内,用于 sinterstore 搜索
127
131
  words += condition_keys
@@ -129,30 +133,30 @@ class Redis
129
133
 
130
134
  return result if words.blank?
131
135
 
132
- temp_store_key = "tmpinterstore:#{words.join("+")}"
136
+ temp_store_key = "tmpinterstore:#{words.join('+')}"
133
137
 
134
138
  if words.length > 1
135
- if !self.config.redis.exists(temp_store_key)
136
- self.config.redis.pipelined do
139
+ unless config.redis.exists(temp_store_key)
140
+ config.redis.pipelined do
137
141
  # 将多个词语组合对比,得到交集,并存入临时区域
138
- self.config.redis.sinterstore(temp_store_key,*words)
142
+ config.redis.sinterstore(temp_store_key, *words)
139
143
  # 将临时搜索设为1天后自动清除
140
- self.config.redis.expire(temp_store_key,86400)
144
+ config.redis.expire(temp_store_key, 86_400)
141
145
 
142
146
  # 拼音搜索
143
- if self.config.pinyin_match
144
- pinyin_words = self.split_pinyin(text)
145
- pinyin_words = pinyin_words.collect { |w| self.mk_sets_key(type,w) }
147
+ if config.pinyin_match
148
+ pinyin_words = split_pinyin(text)
149
+ pinyin_words = pinyin_words.collect { |w| mk_sets_key(type, w) }
146
150
  pinyin_words += condition_keys
147
- temp_sunion_key = "tmpsunionstore:#{words.join("+")}"
148
- temp_pinyin_store_key = "tmpinterstore:#{pinyin_words.join("+")}"
151
+ temp_sunion_key = "tmpsunionstore:#{words.join('+')}"
152
+ temp_pinyin_store_key = "tmpinterstore:#{pinyin_words.join('+')}"
149
153
  # 找出拼音的
150
- self.config.redis.sinterstore(temp_pinyin_store_key,*pinyin_words)
154
+ config.redis.sinterstore(temp_pinyin_store_key, *pinyin_words)
151
155
  # 合并中文和拼音的搜索结果
152
- self.config.redis.sunionstore(temp_sunion_key,*[temp_store_key,temp_pinyin_store_key])
156
+ config.redis.sunionstore(temp_sunion_key, *[temp_store_key, temp_pinyin_store_key])
153
157
  # 将临时搜索设为1天后自动清除
154
- self.config.redis.expire(temp_pinyin_store_key,86400)
155
- self.config.redis.expire(temp_sunion_key,86400)
158
+ config.redis.expire(temp_pinyin_store_key, 86_400)
159
+ config.redis.expire(temp_sunion_key, 86_400)
156
160
  end
157
161
  temp_store_key = temp_sunion_key
158
162
  end
@@ -162,27 +166,29 @@ class Redis
162
166
  end
163
167
 
164
168
  # 根据需要的数量取出 ids
165
- ids = self.config.redis.sort(temp_store_key,
166
- limit: [0,limit],
167
- by: self.mk_score_key(type,"*"),
168
- order: "desc")
169
- result = self.hmget(type, ids, sort_field: sort_field)
170
- self.info("{#{type} : \"#{text}\"} | Time spend: #{Time.now - tm}s")
169
+ ids = config.redis.sort(temp_store_key,
170
+ limit: [0, limit],
171
+ by: mk_score_key(type, '*'),
172
+ order: 'desc')
173
+ result = hmget(type, ids, sort_field: sort_field)
174
+ info("{#{type} : \"#{text}\"} | Time spend: #{Time.now - tm}s")
171
175
  result
172
176
  end
173
177
  end # end class << self
174
178
 
175
179
  protected
180
+
176
181
  def self.split_pinyin(text)
177
182
  # Pinyin search split as pinyin again
178
183
  _split(PinYin.sentence(text))
179
184
  end
180
185
 
181
186
  private
187
+
182
188
  def self._split(text)
183
189
  return [] if text.blank?
184
190
  # return chars if disabled rmmseg
185
- return text.split("") if Search.config.disable_rmmseg
191
+ return text.split('') if Search.config.disable_rmmseg
186
192
 
187
193
  algor = RMMSeg::Algorithm.new(text)
188
194
  words = []
@@ -195,8 +201,8 @@ class Redis
195
201
  end
196
202
 
197
203
  def self.warn(msg)
198
- return if not Redis::Search.config.debug
199
- msg = "\e[33m[Redis::Search] #{msg}\e[0m"
204
+ return unless Redis::Search.config.debug
205
+ msg = "\e[33m[redis-search] #{msg}\e[0m"
200
206
  if defined?(Rails) == 'constant' && Rails.class == Class
201
207
  ::Rails.logger.warn(msg)
202
208
  else
@@ -205,8 +211,8 @@ class Redis
205
211
  end
206
212
 
207
213
  def self.info(msg)
208
- return if not Redis::Search.config.debug
209
- msg = "\e[32m[Redis::Search] #{msg}\e[0m"
214
+ return unless Redis::Search.config.debug
215
+ msg = "\e[32m[redis-search] #{msg}\e[0m"
210
216
  if defined?(Rails) == 'constant' && Rails.class == Class
211
217
  ::Rails.logger.debug(msg)
212
218
  else
@@ -233,13 +239,12 @@ class Redis
233
239
 
234
240
  def self.hmget(type, ids, options = {})
235
241
  result = []
236
- sort_field = options[:sort_field] || "id"
237
242
  return result if ids.blank?
238
- self.config.redis.hmget(type,*ids).each do |r|
243
+ config.redis.hmget(type, *ids).each do |r|
239
244
  begin
240
- result << JSON.parse(r) if !r.blank?
245
+ result << JSON.parse(r) unless r.blank?
241
246
  rescue => e
242
- self.warn("Search.query failed: #{e}")
247
+ warn("Search.query failed: #{e}")
243
248
  end
244
249
  end
245
250
  result
@@ -2,7 +2,8 @@
2
2
  class Redis
3
3
  module Search
4
4
  class Index
5
- attr_accessor :type, :title, :id, :score, :aliases, :exts, :condition_fields, :prefix_index_enable
5
+ attr_accessor :type, :title, :id, :score, :aliases, :exts,
6
+ :condition_fields, :prefix_index_enable
6
7
 
7
8
  class << self
8
9
  def redis
@@ -12,17 +13,17 @@ class Redis
12
13
  def remove(options = {})
13
14
  type = options[:type]
14
15
 
15
- self.redis.pipelined do
16
- self.redis.hdel(type,options[:id])
17
- self.redis.del(Search.mk_score_key(type,options[:id]))
16
+ redis.pipelined do
17
+ redis.hdel(type, options[:id])
18
+ redis.del(Search.mk_score_key(type, options[:id]))
18
19
 
19
- words = self.split_words_for_index(options[:title])
20
+ words = split_words_for_index(options[:title])
20
21
  words.each do |word|
21
- self.redis.srem(Search.mk_sets_key(type,word), options[:id])
22
+ redis.srem(Search.mk_sets_key(type, word), options[:id])
22
23
  end
23
24
 
24
25
  # remove set for prefix index key
25
- self.redis.srem(Search.mk_sets_key(type,options[:title]),options[:id])
26
+ redis.srem(Search.mk_sets_key(type, options[:title]), options[:id])
26
27
  end
27
28
  end
28
29
 
@@ -31,7 +32,7 @@ class Redis
31
32
  if Search.config.pinyin_match
32
33
  # covert Chinese to pinyin to as an index
33
34
  pinyin_full = Search.split_pinyin(title)
34
- pinyin_first = pinyin_full.collect { |p| p[0] }.join("")
35
+ pinyin_first = pinyin_full.collect { |p| p[0] }.join('')
35
36
  words += pinyin_full
36
37
  words << pinyin_first
37
38
  pinyin_full = nil
@@ -61,38 +62,38 @@ class Redis
61
62
 
62
63
  # set attributes value from params
63
64
  options.keys.each do |k|
64
- self.send("#{k}=", options[k])
65
+ send("#{k}=", options[k])
65
66
  end
66
- @aliases << self.title
67
+ @aliases << title
67
68
  @aliases.uniq!
68
69
  end
69
70
 
70
71
  def save
71
72
  return if @title.blank?
72
73
 
73
- self.redis.pipelined do
74
- data = {title: @title, id: @id, type: @type}
75
- self.exts.each do |f|
74
+ redis.pipelined do
75
+ data = { title: @title, id: @id, type: @type }
76
+ exts.each do |f|
76
77
  data[f[0]] = f[1]
77
78
  end
78
79
 
79
80
  # 将原始数据存入 hashes
80
- res = self.redis.hset(@type, @id, data.to_json)
81
+ res = redis.hset(@type, @id, data.to_json)
81
82
 
82
83
  # 将目前的编号保存到条件(conditions)字段所创立的索引上面
83
- self.condition_fields.each do |field|
84
- self.redis.sadd(Search.mk_condition_key(@type,field,data[field.to_sym]), @id)
84
+ condition_fields.each do |field|
85
+ redis.sadd(Search.mk_condition_key(@type, field, data[field.to_sym]), @id)
85
86
  end
86
87
 
87
88
  # score for search sort
88
- self.redis.set(Search.mk_score_key(@type,@id),@score)
89
+ redis.set(Search.mk_score_key(@type, @id), @score)
89
90
 
90
91
  # 保存 sets 索引,以分词的单词为key,用于后面搜索,里面存储 ids
91
- self.aliases.each do |val|
92
+ aliases.each do |val|
92
93
  words = Search::Index.split_words_for_index(val)
93
94
  next if words.blank?
94
95
  words.each do |word|
95
- self.redis.sadd(Search.mk_sets_key(@type,word), @id)
96
+ redis.sadd(Search.mk_sets_key(@type, word), @id)
96
97
  end
97
98
  end
98
99
 
@@ -102,25 +103,26 @@ class Redis
102
103
  end
103
104
 
104
105
  private
106
+
105
107
  def save_prefix_index
106
108
  sorted_set_key = Search.mk_complete_key(@type)
107
109
  sorted_vals = []
108
110
 
109
- self.aliases.each do |val|
111
+ aliases.each do |val|
110
112
  words = []
111
113
  words << val.downcase
112
114
 
113
- self.redis.sadd(Search.mk_sets_key(@type,val), @id)
115
+ redis.sadd(Search.mk_sets_key(@type, val), @id)
114
116
 
115
117
  if Search.config.pinyin_match
116
118
  pinyin_full = Search.split_pinyin(val.downcase)
117
- pinyin_first = pinyin_full.collect { |p| p[0] }.join("")
118
- pinyin = pinyin_full.join("")
119
+ pinyin_first = pinyin_full.collect { |p| p[0] }.join('')
120
+ pinyin = pinyin_full.join('')
119
121
 
120
122
  words << pinyin
121
123
  words << pinyin_first
122
124
 
123
- self.redis.sadd(Search.mk_sets_key(@type,pinyin), @id)
125
+ redis.sadd(Search.mk_sets_key(@type, pinyin), @id)
124
126
 
125
127
  pinyin_full = nil
126
128
  pinyin_first = nil
@@ -136,9 +138,8 @@ class Redis
136
138
  end
137
139
  end
138
140
 
139
- self.redis.zadd(sorted_set_key, sorted_vals)
141
+ redis.zadd(sorted_set_key, sorted_vals)
140
142
  end
141
-
142
143
  end # end Index
143
144
  end
144
145
  end
@@ -1,5 +1,5 @@
1
- # coding: utf-8
2
- require "redis-search"
1
+ require 'redis-search'
2
+
3
3
  namespace :redis_search do
4
4
  task index: 'index:all'
5
5
 
@@ -27,18 +27,18 @@ namespace :redis_search do
27
27
  desc index_model_desc
28
28
  task model: :environment do
29
29
  if ENV['CLASS'].to_s == ''
30
- puts '='*90, 'USAGE', '='*90, index_model_desc, ""
30
+ puts '=' * 90, 'USAGE', '=' * 90, index_model_desc, ''
31
31
  exit(1)
32
32
  end
33
33
 
34
34
  klass = eval(ENV['CLASS'].to_s)
35
35
  batch = ENV['BATCH'].to_i > 0 ? ENV['BATCH'].to_i : 1000
36
36
  tm = Time.now
37
- puts "Redis-Search index data to Redis from [#{klass.to_s}]"
37
+ puts "Redis-Search index data to Redis from [#{klass}]"
38
38
  count = klass.redis_search_index_batch_create(batch, true)
39
- puts ""
39
+ puts ''
40
40
  puts "Indexed #{count} rows | Time spend: #{(Time.now - tm)}s"
41
- puts "Rebuild Index done."
41
+ puts 'Rebuild Index done.'
42
42
  end
43
43
 
44
44
  desc index_all_desc
@@ -51,23 +51,23 @@ namespace :redis_search do
51
51
  Dir.glob(File.join("#{dir}/**/*.rb")).each do |path|
52
52
  model_filename = path[/#{Regexp.escape(dir.to_s)}\/([^\.]+).rb/, 1]
53
53
 
54
- next if model_filename.match(/^concerns\//i) # Skip concerns/ folder
54
+ next if model_filename =~ /^concerns\//i # Skip concerns/ folder
55
55
 
56
56
  begin
57
57
  klass = model_filename.camelize.constantize
58
58
  rescue NameError
59
- require(path) ? retry : raise(RuntimeError, "Cannot load class '#{klass}'")
59
+ require(path) ? retry : raise("Cannot load class '#{klass}'")
60
60
  end
61
61
  end
62
62
 
63
63
  puts "Redis-Search index data to Redis from [#{dir}]"
64
64
  Redis::Search.indexed_models.each do |klass|
65
- puts "[#{klass.to_s}]"
65
+ puts "[#{klass}]"
66
66
  count += klass.redis_search_index_batch_create(batch, true)
67
- puts ""
67
+ puts ''
68
68
  end
69
69
  puts "Indexed #{count} rows | Time spend: #{(Time.now - tm)}s"
70
- puts "Rebuild Index done."
70
+ puts 'Rebuild Index done.'
71
71
  end
72
72
  end
73
73
  end
@@ -0,0 +1,5 @@
1
+ class Redis
2
+ module Search
3
+ VERSION = '1.0.0.beta1'
4
+ end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 1.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Lee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-08 00:00:00.000000000 Z
11
+ date: 2016-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-pinyin
@@ -69,12 +69,13 @@ files:
69
69
  - LICENSE
70
70
  - README.md
71
71
  - lib/redis-search.rb
72
- - lib/redis/search/base.rb
73
- - lib/redis/search/config.rb
74
- - lib/redis/search/finder.rb
75
- - lib/redis/search/index.rb
76
- - lib/redis/search/railtie.rb
77
- - lib/redis/search/tasks.rb
72
+ - lib/redis-search/base.rb
73
+ - lib/redis-search/config.rb
74
+ - lib/redis-search/finder.rb
75
+ - lib/redis-search/index.rb
76
+ - lib/redis-search/railtie.rb
77
+ - lib/redis-search/tasks.rb
78
+ - lib/redis-search/version.rb
78
79
  homepage: http://github.com/huacnlee/redis-search
79
80
  licenses:
80
81
  - MIT
@@ -95,10 +96,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
96
  version: 1.3.6
96
97
  requirements: []
97
98
  rubyforge_project:
98
- rubygems_version: 2.2.2
99
+ rubygems_version: 2.5.1
99
100
  signing_key:
100
101
  specification_version: 4
101
102
  summary: High performance real-time search (Support Chinese), indexes store in Redis
102
103
  for Rails applications.
103
104
  test_files: []
104
- has_rdoc: