elastic_searchable 1.4.1 → 1.5

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.
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