elastic_searchable 1.4.1 → 1.5

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm use ruby-1.9.2@elastic_searchable --create
1
+ rvm use ruby-1.9.3-p125@elastic_searchable --create
@@ -21,11 +21,11 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_runtime_dependency(%q<activerecord>, [">= 3.0.5"])
23
23
  s.add_runtime_dependency(%q<httparty>, [">= 0.6.0"])
24
- s.add_runtime_dependency(%q<backgrounded>, [">= 0.7.0"])
24
+ s.add_runtime_dependency(%q<backgrounded>, ["~> 0.7.0"])
25
25
  s.add_runtime_dependency(%q<multi_json>, [">= 1.0.0"])
26
26
  s.add_development_dependency(%q<rake>, ["0.9.2.2"])
27
- s.add_development_dependency(%q<sqlite3>, ["1.3.4"])
27
+ s.add_development_dependency(%q<sqlite3>)
28
28
  s.add_development_dependency(%q<pry>, ["0.9.6.2"])
29
29
  s.add_development_dependency(%q<shoulda>, ["2.11.3"])
30
- s.add_development_dependency(%q<mocha>, ["0.10.0"])
30
+ s.add_development_dependency(%q<mocha>)
31
31
  end
@@ -70,7 +70,7 @@ module ElasticSearchable
70
70
  scope = options.delete(:scope) || self
71
71
  page = options[:page]
72
72
  per_page = options[:per_page]
73
- records = scope.limit(per_page).offset(per_page * (page -1)).all
73
+ records = scope.limit(per_page).offset(per_page * (page -1)).to_a
74
74
  while records.any? do
75
75
  ElasticSearchable.logger.debug "reindexing batch ##{page}..."
76
76
  actions = []
@@ -92,7 +92,7 @@ module ElasticSearchable
92
92
  end
93
93
 
94
94
  page += 1
95
- records = scope.limit(per_page).offset(per_page* (page-1)).all
95
+ records = scope.limit(per_page).offset(per_page* (page-1)).to_a
96
96
  end
97
97
  end
98
98
 
@@ -1,6 +1,7 @@
1
1
  module ElasticSearchable
2
2
  module Queries
3
3
  PER_PAGE_DEFAULT = 20
4
+ MAX_RETRIES = 5
4
5
 
5
6
  def per_page
6
7
  PER_PAGE_DEFAULT
@@ -14,8 +15,8 @@ module ElasticSearchable
14
15
  # http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/
15
16
  def search(query, options = {})
16
17
  page = (options.delete(:page) || 1).to_i
18
+ size = (options[:size] ||= per_page_for_search(options))
17
19
  options[:fields] ||= '_id'
18
- options[:size] ||= per_page_for_search(options)
19
20
  options[:from] ||= options[:size] * (page - 1)
20
21
  if query.is_a?(Hash)
21
22
  options[:query] = query
@@ -35,19 +36,51 @@ module ElasticSearchable
35
36
  query[:sort] = sort
36
37
  end
37
38
 
38
- response = ElasticSearchable.request :get, index_type_path('_search'), :query => query, :json_body => options
39
- hits = response['hits']
40
- ids = hits['hits'].collect {|h| h['_id'].to_i }
41
- results = self.find(ids).sort_by {|result| ids.index(result.id) }
39
+ ids_to_delete = []
40
+ results = []
41
+ ids = []
42
+ hits_total = nil
43
+ retries = MAX_RETRIES
42
44
 
43
- results.each do |result|
44
- result.instance_variable_set '@hit', hits['hits'][ids.index(result.id)]
45
+ loop do
46
+ response = ElasticSearchable.request :get, index_type_path('_search'), :query => query, :json_body => options
47
+ hits = response['hits']
48
+ hits_total ||= hits['total'].to_i
49
+ new_ids = collect_hit_ids(hits)
50
+ new_results = collect_result_records(new_ids, hits)
51
+ ids += new_ids
52
+ results += new_results
53
+
54
+ break if results.size >= ids.size || retries <= 0
55
+
56
+ retries -= 1
57
+
58
+ options[:from] = options[:from] + options[:size]
59
+ options[:size] = ids.size - results.size
60
+
61
+ ids_to_delete += (new_ids - new_results.map(&:id))
62
+ ids -= ids_to_delete
63
+ end
64
+
65
+ ids_to_delete.each do |id|
66
+ delete_id_from_index_backgrounded id
45
67
  end
46
68
 
47
- ElasticSearchable::Paginator.handler.new(results, page, options[:size], hits['total'])
69
+ ElasticSearchable::Paginator.handler.new(results, page, size, hits_total - ids_to_delete.size)
48
70
  end
49
71
 
50
72
  private
73
+
74
+ def collect_hit_ids(hits)
75
+ hits['hits'].collect {|h| h['_id'].to_i }
76
+ end
77
+
78
+ def collect_result_records(ids, hits)
79
+ self.where(:id => ids).to_a.sort_by{ |result| ids.index(result.id) }.each do |result|
80
+ result.instance_variable_set '@hit', hits['hits'][ids.index(result.id)]
81
+ end
82
+ end
83
+
51
84
  # determine the number of search results per page
52
85
  # supports will_paginate configuration by using:
53
86
  # Model.per_page
@@ -1,3 +1,3 @@
1
1
  module ElasticSearchable
2
- VERSION = '1.4.1'
2
+ VERSION = '1.5'
3
3
  end
data/test/helper.rb CHANGED
@@ -9,7 +9,7 @@ rescue Bundler::BundlerError => e
9
9
  end
10
10
  require 'test/unit'
11
11
  require 'shoulda'
12
- require 'mocha'
12
+ require 'mocha/setup'
13
13
  require 'pry'
14
14
 
15
15
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
@@ -17,6 +17,19 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
17
17
  require 'elastic_searchable'
18
18
  require 'setup_database'
19
19
 
20
+ class DeprecationLogger < Logger
21
+ def format_message(severity, timestamp, progname, msg)
22
+ "#{severity} #{msg}\n"
23
+ end
24
+ end
25
+
26
+ DEPRECATION_LOGGER = DeprecationLogger.new(File.join(File.dirname(__FILE__), "/deprecations.log"))
27
+ ActiveSupport::Deprecation.debug = false
28
+ ActiveSupport::Deprecation::DEFAULT_BEHAVIORS[:deprecation_log] = lambda { |message, callstack|
29
+ DEPRECATION_LOGGER.warn(message)
30
+ }
31
+ ActiveSupport::Deprecation.behavior = :deprecation_log
32
+
20
33
  class Test::Unit::TestCase
21
34
  def delete_index
22
35
  ElasticSearchable.delete '/elastic_searchable' rescue nil
@@ -160,7 +160,7 @@ class TestElasticSearchable < Test::Unit::TestCase
160
160
  end
161
161
  context 'Model.reindex' do
162
162
  setup do
163
- Post.reindex :per_page => 1, :scope => Post.scoped(:order => 'body desc')
163
+ Post.reindex :per_page => 1, :scope => Post.order('body desc')
164
164
  Post.refresh_index
165
165
  end
166
166
  should 'have reindexed both records' do
@@ -288,6 +288,39 @@ class TestElasticSearchable < Test::Unit::TestCase
288
288
  end
289
289
  end
290
290
 
291
+ context 'deleting a record without updating the index' do
292
+
293
+ context 'backfilling partial result pages' do
294
+ setup do
295
+ @posts = (1..8).map do |i|
296
+ Post.create :title => 'foo', :body => "#{i} bar"
297
+ end
298
+ Post.refresh_index
299
+
300
+ @removed_posts = []
301
+ @posts.each_with_index do |post, i|
302
+ if i % 2 == 1
303
+ @removed_posts << post
304
+ post.delete
305
+ Post.expects(:delete_id_from_index_backgrounded).with(post.id)
306
+ end
307
+ end
308
+
309
+ assert_nothing_raised do
310
+ @results = Post.search 'foo', :size => 4, :sort => 'id:desc'
311
+ end
312
+ end
313
+ # should 'not raise an exception' do end
314
+ # should 'trigger deletion of bad index records' do end
315
+ should 'backfill the first page with results from other pages' do
316
+ assert_equal((@posts - @removed_posts).reverse, @results)
317
+ end
318
+ should 'adjust total hit count to exclude invalid results encountered from repaging' do
319
+ assert_equal 4, @results.total_entries
320
+ end
321
+ end
322
+
323
+ end
291
324
 
292
325
  class Blog < ActiveRecord::Base
293
326
  elastic_searchable :if => proc {|b| b.should_index? }, :index_options => SINGLE_NODE_CLUSTER_CONFIG
@@ -324,6 +357,7 @@ class TestElasticSearchable < Test::Unit::TestCase
324
357
  end
325
358
  should 'have used custom index_options' do
326
359
  @status = ElasticSearchable.request :get, '/elastic_searchable/_settings'
360
+ @status['elastic_searchable']['settings'].delete('index.version.created')
327
361
  expected = {
328
362
  "index.number_of_replicas" => "0",
329
363
  "index.number_of_shards" => "1",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic_searchable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: '1.5'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-22 00:00:00.000000000 Z
12
+ date: 2013-08-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -48,7 +48,7 @@ dependencies:
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ! '>='
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
53
  version: 0.7.0
54
54
  type: :runtime
@@ -56,7 +56,7 @@ dependencies:
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ! '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.7.0
62
62
  - !ruby/object:Gem::Dependency
@@ -96,17 +96,17 @@ dependencies:
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
99
- - - '='
99
+ - - ! '>='
100
100
  - !ruby/object:Gem::Version
101
- version: 1.3.4
101
+ version: '0'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
- - - '='
107
+ - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
- version: 1.3.4
109
+ version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: pry
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -144,17 +144,17 @@ dependencies:
144
144
  requirement: !ruby/object:Gem::Requirement
145
145
  none: false
146
146
  requirements:
147
- - - '='
147
+ - - ! '>='
148
148
  - !ruby/object:Gem::Version
149
- version: 0.10.0
149
+ version: '0'
150
150
  type: :development
151
151
  prerelease: false
152
152
  version_requirements: !ruby/object:Gem::Requirement
153
153
  none: false
154
154
  requirements:
155
- - - '='
155
+ - - ! '>='
156
156
  - !ruby/object:Gem::Version
157
- version: 0.10.0
157
+ version: '0'
158
158
  description: integrate the elastic search engine with rails
159
159
  email:
160
160
  - ryan@codecrate.com
@@ -196,18 +196,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
196
196
  - - ! '>='
197
197
  - !ruby/object:Gem::Version
198
198
  version: '0'
199
- segments:
200
- - 0
201
- hash: 3119629998043065822
202
199
  required_rubygems_version: !ruby/object:Gem::Requirement
203
200
  none: false
204
201
  requirements:
205
202
  - - ! '>='
206
203
  - !ruby/object:Gem::Version
207
204
  version: '0'
208
- segments:
209
- - 0
210
- hash: 3119629998043065822
211
205
  requirements: []
212
206
  rubyforge_project: elastic_searchable
213
207
  rubygems_version: 1.8.24