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 +1 -1
- data/elastic_searchable.gemspec +3 -3
- data/lib/elastic_searchable/index.rb +2 -2
- data/lib/elastic_searchable/queries.rb +41 -8
- data/lib/elastic_searchable/version.rb +1 -1
- data/test/helper.rb +14 -1
- data/test/test_elastic_searchable.rb +35 -1
- metadata +12 -18
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm use ruby-1.9.
|
1
|
+
rvm use ruby-1.9.3-p125@elastic_searchable --create
|
data/elastic_searchable.gemspec
CHANGED
@@ -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>, ["
|
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
|
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
|
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)).
|
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)).
|
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
|
-
|
39
|
-
|
40
|
-
ids =
|
41
|
-
|
39
|
+
ids_to_delete = []
|
40
|
+
results = []
|
41
|
+
ids = []
|
42
|
+
hits_total = nil
|
43
|
+
retries = MAX_RETRIES
|
42
44
|
|
43
|
-
|
44
|
-
|
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,
|
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
|
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.
|
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
|
+
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-
|
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:
|
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:
|
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
|
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
|
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
|