elastics 0.2.0 → 0.3.0
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 +4 -4
- data/.travis.yml +2 -0
- data/README.md +45 -9
- data/lib/elastics/active_record/helper_methods.rb +50 -12
- data/lib/elastics/active_record/instrumentation.rb +1 -1
- data/lib/elastics/active_record/search_result.rb +5 -31
- data/lib/elastics/auto_refresh.rb +48 -0
- data/lib/elastics/client/bulk.rb +49 -0
- data/lib/elastics/client.rb +20 -5
- data/lib/elastics/result/search.rb +43 -0
- data/lib/elastics/result.rb +5 -0
- data/lib/elastics/tasks/indices.rb +2 -2
- data/lib/elastics/tasks/mappings.rb +1 -1
- data/lib/elastics/tasks/migrations.rb +15 -4
- data/lib/elastics/version.rb +1 -1
- data/lib/elastics/version_manager.rb +1 -1
- data/lib/elastics.rb +5 -5
- data/spec/lib/elastics/auto_refresh_spec.rb +36 -0
- data/spec/lib/elastics/client/bulk_spec.rb +57 -0
- data/spec/lib/elastics/client_spec.rb +34 -0
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5c6528a83756461e3f88a64c932e6f6cd4a572e
|
4
|
+
data.tar.gz: 329c63ad74333cee9dc57581ca8ac626973dea3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aba73c791bb368035b51ed5d93994fa27648c442f77ed7992749b5bb5ee5ee823a17e33d5449d0d8a1f293dd830ff01501405287ca1dc563df644c3bb3da68ba
|
7
|
+
data.tar.gz: d687176c8013f6196d0ebc0340aaa6e194e5719b700fdbb688159ca2ca6ffda3694e144e0b55c064fcb63b629299288121b9dbd25ba61876318092089360cafa
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -3,10 +3,12 @@
|
|
3
3
|
[](https://codeclimate.com/github/printercu/elastics-rb)
|
4
4
|
[](https://travis-ci.org/printercu/elastics-rb)
|
5
5
|
|
6
|
-
Simple ElasticSearch client.
|
7
|
-
-
|
8
|
-
-
|
9
|
-
-
|
6
|
+
Simple ElasticSearch client. Everything for deployment & maintaince included.
|
7
|
+
- Basic API only
|
8
|
+
- Transparent aliases management & zero-downtime migrations
|
9
|
+
- Capistrano integration
|
10
|
+
- Auto refresh in tests
|
11
|
+
- Instrumentation
|
10
12
|
|
11
13
|
Fast and thread-safe [httpclient](https://github.com/nahi/httpclient) is under the hood.
|
12
14
|
|
@@ -14,7 +16,7 @@ Fast and thread-safe [httpclient](https://github.com/nahi/httpclient) is under t
|
|
14
16
|
|
15
17
|
```ruby
|
16
18
|
# Gemfile
|
17
|
-
gem 'elastics', '~> 0.
|
19
|
+
gem 'elastics', '~> 0.3' # use version from the badge above
|
18
20
|
# or
|
19
21
|
gem 'elastics', github: 'printercu/elastics-rb'
|
20
22
|
```
|
@@ -34,10 +36,10 @@ client = Elastics::Client.new(options)
|
|
34
36
|
# :resurrect_timeout - timeout to mark dead host as alive in cluster-mode (default 10)
|
35
37
|
|
36
38
|
# basic request
|
37
|
-
client.request(
|
38
|
-
#
|
39
|
+
client.request(params)
|
40
|
+
# params is hash with
|
39
41
|
# :method - default :get
|
40
|
-
# :
|
42
|
+
# :body - post body
|
41
43
|
# :query - query string params
|
42
44
|
# :index, :type, :id - query path params to override defaults
|
43
45
|
|
@@ -50,12 +52,22 @@ client.get(id)
|
|
50
52
|
client.get(params) # as usual
|
51
53
|
|
52
54
|
# other shortcuts (set method & id)
|
53
|
-
client.put_mapping(index: index, type: type,
|
55
|
+
client.put_mapping(index: index, type: type, body: mapping)
|
54
56
|
client.search(params)
|
55
57
|
client.index(params) # PUT if :id is set, otherwise POST
|
56
58
|
|
57
59
|
# utils
|
58
60
|
client.index_exists?(name)
|
61
|
+
|
62
|
+
# bulk
|
63
|
+
client.bulk(params) do |bulk|
|
64
|
+
# if first param is not a Hash it's converted to {_id: param}
|
65
|
+
bulk.index override_params, data
|
66
|
+
bulk.create id, data
|
67
|
+
bulk.update id, script
|
68
|
+
bulk.update_doc id, fields
|
69
|
+
bulk.delete id
|
70
|
+
end
|
59
71
|
```
|
60
72
|
|
61
73
|
When using cluster-mode you should also install `gem 'thread_safe'`.
|
@@ -65,6 +77,7 @@ When using cluster-mode you should also install `gem 'thread_safe'`.
|
|
65
77
|
```ruby
|
66
78
|
class User < ActiveRecord::Base
|
67
79
|
indexed_with_elastics
|
80
|
+
# it'll set after_commit callbacks and add helper methods
|
68
81
|
# optionally pass :index, :type
|
69
82
|
|
70
83
|
# optionally override to export only selected fields
|
@@ -73,9 +86,14 @@ class User < ActiveRecord::Base
|
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
89
|
+
User.elastics # Elastics::Client instance
|
90
|
+
User.elastics_params # hash with index & type values for the model
|
91
|
+
User.request_elastics(params) # performs request merging params with elastics_params
|
76
92
|
User.search_elastics(data)
|
77
93
|
# Returns Elastics::ActiveRecord::SearchResult object with some useful methods
|
78
94
|
```
|
95
|
+
Check out [HelperMethods](https://github.com/printercu/elastics-rb/blob/master/lib/elastics/active_record/helper_methods.rb)
|
96
|
+
for more information.
|
79
97
|
|
80
98
|
#### Configure
|
81
99
|
```yml
|
@@ -156,6 +174,21 @@ end
|
|
156
174
|
Also you need to install `active_support` & require
|
157
175
|
`active_support/core_ext/object` to be able to run tasks.
|
158
176
|
|
177
|
+
### Auto refresh index
|
178
|
+
Add `Elastics::AutoRefresh.enable!` to your test helper,
|
179
|
+
this will run `POST /:index/_refresh` request after each modifying request.
|
180
|
+
You can also use it for a block or skip auto refresh after it was enabled:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
# enable test mode in rspec's around filter
|
184
|
+
around { |ex| Elastics::AutoRefresh.enable! { ex.run } }
|
185
|
+
|
186
|
+
# disable auto refresh for block & perform single refresh
|
187
|
+
# assume test mode is enabled here
|
188
|
+
Elastics::AutoRefresh.disable! { Model.reindex_elastics }
|
189
|
+
Model.refresh_elastics
|
190
|
+
```
|
191
|
+
|
159
192
|
### Use with capistrano
|
160
193
|
Add following lines to your `deploy.rb` and all rake tasks will be available in cap.
|
161
194
|
|
@@ -170,5 +203,8 @@ Indices & rake options can be passed like this:
|
|
170
203
|
cap --dry-run elastics:migrate INDICES=index1,index2 ES_OPTIONS='full=true no_drop=true'
|
171
204
|
```
|
172
205
|
|
206
|
+
## Other versions
|
207
|
+
[elastics for node.js](https://github.com/printercu/elastics)
|
208
|
+
|
173
209
|
## License
|
174
210
|
MIT
|
@@ -8,19 +8,26 @@ module Elastics
|
|
8
8
|
end
|
9
9
|
|
10
10
|
module ClassMethods
|
11
|
-
def
|
12
|
-
|
11
|
+
def elastics_params
|
12
|
+
{
|
13
13
|
index: elastics_index_name,
|
14
14
|
type: elastics_type_name,
|
15
15
|
model: self,
|
16
|
-
}
|
17
|
-
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def request_elastics(params)
|
20
|
+
elastics.request(elastics_params.merge!(params))
|
21
|
+
end
|
22
|
+
|
23
|
+
def bulk_elastics(params = {}, &block)
|
24
|
+
elastics.bulk(elastics_params.merge!(params), &block)
|
18
25
|
end
|
19
26
|
|
20
27
|
def search_elastics(data = {}, options = {})
|
21
28
|
request = {
|
22
29
|
id: :_search,
|
23
|
-
|
30
|
+
body: data,
|
24
31
|
}
|
25
32
|
if routing = options[:routing]
|
26
33
|
request[:query] = {routing: routing}
|
@@ -37,23 +44,54 @@ module Elastics
|
|
37
44
|
request_elastics(method: :get, id: :_mapping)
|
38
45
|
end
|
39
46
|
|
40
|
-
def
|
41
|
-
|
47
|
+
def index_all_elastics(*args)
|
48
|
+
find_in_batches(*args) do |batch|
|
49
|
+
bulk_elastics do |bulk|
|
50
|
+
batch.each do |record|
|
51
|
+
bulk.index record.id, record.to_elastics
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Reindexes records with `#index_all_elastics`. If model has scope
|
58
|
+
# named `reindex_scope`, this method will apply it.
|
59
|
+
#
|
60
|
+
# Also supports `:updated_after` option to reindex only updated records.
|
61
|
+
# Nothing is performed when `:updated_after` is set but model
|
62
|
+
# has not `updated_at` column.
|
63
|
+
def reindex_elastics(options = {})
|
64
|
+
scope = respond_to?(:reindex_scope) ? reindex_scope : all
|
65
|
+
if after = options.delete(:updated_after)
|
66
|
+
if updated_at = arel_table[:updated_at]
|
67
|
+
scope = scope.where(updated_at.gt(after))
|
68
|
+
else
|
69
|
+
return
|
70
|
+
end
|
71
|
+
end
|
72
|
+
scope.index_all_elastics(options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def refresh_elastics
|
76
|
+
request_elastics(method: :post, type: nil, id: :_refresh)
|
42
77
|
end
|
43
78
|
end
|
44
79
|
|
45
80
|
def index_elastics
|
46
|
-
self.class.request_elastics(method: :post, id: id,
|
81
|
+
self.class.request_elastics(method: :post, id: id, body: to_elastics)
|
82
|
+
end
|
83
|
+
|
84
|
+
def update_elastics(data)
|
85
|
+
self.class.request_elastics(method: :post, id: "#{id}/_update", body: data)
|
47
86
|
end
|
48
87
|
|
49
|
-
def
|
50
|
-
|
51
|
-
doc: fields
|
52
|
-
})
|
88
|
+
def update_elastics_doc(fields)
|
89
|
+
update_elastics(doc: fields)
|
53
90
|
end
|
54
91
|
|
55
92
|
def delete_elastics
|
56
93
|
self.class.request_elastics(method: :delete, id: id)
|
94
|
+
rescue NotFound
|
57
95
|
end
|
58
96
|
end
|
59
97
|
end
|
@@ -1,48 +1,22 @@
|
|
1
1
|
module Elastics
|
2
2
|
module ActiveRecord
|
3
|
-
class SearchResult
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(model, result, options = {})
|
3
|
+
class SearchResult < Result::Search
|
4
|
+
def initialize(model, response, options = {})
|
7
5
|
@model = model
|
8
|
-
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
def hits
|
13
|
-
@hits ||= @result['hits'.freeze]
|
6
|
+
super response, options
|
14
7
|
end
|
15
8
|
|
9
|
+
# super.map(&:to_i)
|
16
10
|
def ids
|
17
11
|
@ids ||= hits['hits'.freeze].map { |x| x['_id'.freeze].to_i }
|
18
12
|
end
|
19
13
|
|
20
|
-
def ids_to_find
|
21
|
-
@ids_to_find ||= begin
|
22
|
-
limit = @options[:limit]
|
23
|
-
limit ? ids[0...limit] : ids
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def rest_ids
|
28
|
-
limit = @options[:limit]
|
29
|
-
limit ? ids[limit..-1] : []
|
30
|
-
end
|
31
|
-
|
32
14
|
def collection
|
33
15
|
@collection ||= @model.find_all_ordered ids_to_find
|
34
16
|
end
|
35
17
|
|
36
18
|
def relation
|
37
|
-
@model.where
|
38
|
-
end
|
39
|
-
|
40
|
-
def aggregations
|
41
|
-
@aggregations ||= @result['aggregations'.freeze]
|
42
|
-
end
|
43
|
-
|
44
|
-
def total
|
45
|
-
hits['total'.freeze]
|
19
|
+
@model.where(id: ids_to_find)
|
46
20
|
end
|
47
21
|
end
|
48
22
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Elastics
|
2
|
+
module AutoRefresh
|
3
|
+
METHODS = %w(put post patch delete)
|
4
|
+
SKIP_IDS = %w(_refresh _search)
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def enabled?
|
8
|
+
Thread.current[:elastics_test_mode]
|
9
|
+
end
|
10
|
+
|
11
|
+
def enabled=(value)
|
12
|
+
value = !!value
|
13
|
+
Client.send(:include, self) if value && !Client.include?(self)
|
14
|
+
Thread.current[:elastics_test_mode] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def use(value)
|
18
|
+
old_value = enabled?
|
19
|
+
self.enabled = value
|
20
|
+
block_given? ? yield : value
|
21
|
+
ensure
|
22
|
+
self.enabled = old_value if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def enable!(&block)
|
26
|
+
use(true, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def disable!(&block)
|
30
|
+
use(false, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def included(base)
|
34
|
+
base.send :alias_method, :request_without_auto_refresh, :request
|
35
|
+
base.send :alias_method, :request, :request_with_auto_refresh
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def request_with_auto_refresh(params)
|
40
|
+
request_without_auto_refresh(params).tap do
|
41
|
+
next unless AutoRefresh.enabled?
|
42
|
+
next if SKIP_IDS.include?(params[:id].to_s.downcase)
|
43
|
+
next unless METHODS.include?(params[:method].to_s.downcase)
|
44
|
+
refresh(params[:index])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Elastics
|
2
|
+
class Client
|
3
|
+
module Bulk
|
4
|
+
def bulk(params = {})
|
5
|
+
builder = Builder.new
|
6
|
+
yield builder
|
7
|
+
if builder.any?
|
8
|
+
request({body: builder.body, method: :post, id: :_bulk}.merge! params)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Builder
|
13
|
+
attr_reader :actions
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@actions = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def any?
|
20
|
+
@actions.any?
|
21
|
+
end
|
22
|
+
|
23
|
+
def body
|
24
|
+
@actions.map(&:to_json).join("\n".freeze) + "\n"
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_action(action, params, data = nil)
|
28
|
+
params = {_id: params} unless params.is_a?(Hash)
|
29
|
+
@actions << {action => params}
|
30
|
+
@actions << data if data
|
31
|
+
end
|
32
|
+
|
33
|
+
[:index, :create, :update].each do |action|
|
34
|
+
define_method(action) do |params, data|
|
35
|
+
add_action(action, params, data)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_doc(params, fields)
|
40
|
+
update(params, doc: fields)
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete(params)
|
44
|
+
add_action(:delete, params)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/elastics/client.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'json'
|
1
2
|
require 'httpclient'
|
2
3
|
|
3
4
|
module Elastics
|
@@ -6,6 +7,9 @@ module Elastics
|
|
6
7
|
|
7
8
|
autoload :Cluster, 'elastics/client/cluster'
|
8
9
|
|
10
|
+
require 'elastics/client/bulk'
|
11
|
+
include Bulk
|
12
|
+
|
9
13
|
attr_writer :index, :type
|
10
14
|
attr_reader :client
|
11
15
|
|
@@ -46,9 +50,10 @@ module Elastics
|
|
46
50
|
str
|
47
51
|
end
|
48
52
|
|
49
|
-
def request(params)
|
53
|
+
def request(params = {})
|
50
54
|
method = params[:method] || :get
|
51
|
-
body = params[:
|
55
|
+
body = params[:body]
|
56
|
+
body = body.to_json if body && !body.is_a?(String)
|
52
57
|
res = http_request(method, request_path(params), params[:query], body, params)
|
53
58
|
status = res.status
|
54
59
|
return JSON.parse(res.body) if 300 > status
|
@@ -68,6 +73,7 @@ module Elastics
|
|
68
73
|
end
|
69
74
|
|
70
75
|
def delete!(params)
|
76
|
+
params = {id: params} unless params.is_a?(Hash)
|
71
77
|
params[:method] = :delete
|
72
78
|
request params
|
73
79
|
end
|
@@ -89,7 +95,7 @@ module Elastics
|
|
89
95
|
end
|
90
96
|
|
91
97
|
def set(id, data)
|
92
|
-
request(id: id,
|
98
|
+
request(id: id, body: data, method: :put)
|
93
99
|
end
|
94
100
|
|
95
101
|
def put_mapping(params)
|
@@ -98,10 +104,10 @@ module Elastics
|
|
98
104
|
request(params)
|
99
105
|
end
|
100
106
|
|
101
|
-
def search(params)
|
107
|
+
def search(params, *args)
|
102
108
|
params[:id] = :_search
|
103
109
|
params[:method] = :post
|
104
|
-
request(params)
|
110
|
+
Result::Search.new(request(params), *args)
|
105
111
|
end
|
106
112
|
|
107
113
|
def index(params)
|
@@ -112,6 +118,15 @@ module Elastics
|
|
112
118
|
!!get(index: index, type: nil, id: :_mapping)
|
113
119
|
end
|
114
120
|
|
121
|
+
def refresh!(index = nil)
|
122
|
+
request(method: :post, index: index, type: nil, id: :_refresh)
|
123
|
+
end
|
124
|
+
|
125
|
+
def refresh(*args)
|
126
|
+
refresh!(*args)
|
127
|
+
rescue NotFound
|
128
|
+
end
|
129
|
+
|
115
130
|
private
|
116
131
|
# Endpoint for low-level request. For easy host highjacking & instrumentation.
|
117
132
|
# Params are not used directly but kept for instrumentation purpose.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Elastics
|
2
|
+
module Result
|
3
|
+
class Search
|
4
|
+
attr_reader :response
|
5
|
+
|
6
|
+
def initialize(response, options = {})
|
7
|
+
@response = response
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def hits
|
12
|
+
@hits ||= @response['hits'.freeze]
|
13
|
+
end
|
14
|
+
|
15
|
+
def ids
|
16
|
+
@ids ||= hits['hits'.freeze].map { |x| x['_id'.freeze] }
|
17
|
+
end
|
18
|
+
|
19
|
+
# Allows to split ids into two parts, if you want to fetch from primary DB
|
20
|
+
# less then was found. This method returns the first part,
|
21
|
+
# `rest_ids` - the second.
|
22
|
+
def ids_to_find
|
23
|
+
@ids_to_find ||= begin
|
24
|
+
limit = @options[:limit]
|
25
|
+
limit ? ids[0...limit] : ids
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def rest_ids
|
30
|
+
limit = @options[:limit]
|
31
|
+
limit ? ids[limit..-1] : []
|
32
|
+
end
|
33
|
+
|
34
|
+
def aggregations
|
35
|
+
@aggregations ||= @response['aggregations'.freeze]
|
36
|
+
end
|
37
|
+
|
38
|
+
def total
|
39
|
+
hits['total'.freeze]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -58,7 +58,7 @@ module Elastics
|
|
58
58
|
log_msg << ' - Skipping: exists' if exists
|
59
59
|
log log_msg
|
60
60
|
unless exists
|
61
|
-
client.put(index: versioned_index,
|
61
|
+
client.put(index: versioned_index, body: indices_settings[index])
|
62
62
|
end
|
63
63
|
end
|
64
64
|
manage_aliases :add, options if version.to_s == 'current'
|
@@ -97,7 +97,7 @@ module Elastics
|
|
97
97
|
def post_aliases(options = {}, &block)
|
98
98
|
actions = each_filtered(indices, options[:indices]).map(&block).flatten
|
99
99
|
log "Posting aliases: #{actions.inspect}"
|
100
|
-
client.post id: :_aliases,
|
100
|
+
client.post id: :_aliases, body: {actions: actions} if actions.any?
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -17,7 +17,7 @@ module Elastics
|
|
17
17
|
versioned_index = versioned_index_name(index, version)
|
18
18
|
log "Putting mapping #{index}/#{type} (#{versioned_index}/#{type})"
|
19
19
|
client.put_mapping index: versioned_index, type: type,
|
20
|
-
|
20
|
+
body: mappings[type]
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -8,22 +8,33 @@ module Elastics
|
|
8
8
|
|
9
9
|
def migrate!(options = {})
|
10
10
|
options_next = options.merge version: :next
|
11
|
+
need_reindex = options.fetch(:reindex, true)
|
11
12
|
drop_indices(options_next)
|
12
13
|
create_indices(options_next)
|
13
14
|
put_mappings(options_next)
|
14
|
-
reindex(options_next) if
|
15
|
+
started_at = reindex(options_next) if need_reindex
|
15
16
|
forward_aliases(options)
|
17
|
+
if need_reindex
|
18
|
+
reindex(options.merge(version: :current, updated_after: started_at))
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
22
|
+
# Runs `#reindex_elastics` on matching models.
|
23
|
+
# Returns hash with timestamps with reindex start time for each model.
|
24
|
+
# Supports this kind of hash as `:updated_after` option, to reindex
|
25
|
+
# only updated records.
|
18
26
|
def reindex(options = {})
|
19
27
|
version = options.fetch(:version, :current)
|
28
|
+
updated_after = options.fetch(:updated_after, {})
|
20
29
|
Rails.application.eager_load! if defined?(Rails)
|
21
30
|
VersionManager.use_version version do
|
22
|
-
models_to_reindex(options).
|
31
|
+
Hash[models_to_reindex(options).map do |model|
|
32
|
+
started_at = Time.now
|
23
33
|
log "Reindexing #{model.elastics_index_base} into " \
|
24
34
|
"#{model.elastics_index_name}/#{model.elastics_type_name}"
|
25
|
-
model.reindex_elastics
|
26
|
-
|
35
|
+
model.reindex_elastics(updated_after: updated_after[model])
|
36
|
+
[model, started_at]
|
37
|
+
end]
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
data/lib/elastics/version.rb
CHANGED
data/lib/elastics.rb
CHANGED
@@ -3,12 +3,12 @@ module Elastics
|
|
3
3
|
class NotFound < Error; end
|
4
4
|
|
5
5
|
require 'elastics/client'
|
6
|
-
require 'elastics/version_manager'
|
7
|
-
require 'elastics/query_helper'
|
8
6
|
|
9
|
-
autoload :
|
10
|
-
|
11
|
-
|
7
|
+
autoload :AutoRefresh, 'elastics/auto_refresh'
|
8
|
+
autoload :Tasks, 'elastics/tasks'
|
9
|
+
autoload :QueryHelper, 'elastics/query_helper'
|
10
|
+
autoload :Result, 'elastics/result'
|
11
|
+
autoload :VersionManager, 'elastics/version_manager'
|
12
12
|
|
13
13
|
class << self
|
14
14
|
attr_reader :models
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elastics::AutoRefresh do
|
4
|
+
let(:client) { Elastics::Client.new }
|
5
|
+
let(:response) { OpenStruct.new(body: '{}', status: 200) }
|
6
|
+
before { allow(client).to receive(:http_request) { response } }
|
7
|
+
|
8
|
+
describe '.enable!' do
|
9
|
+
around { |ex| described_class.enable! { ex.run } }
|
10
|
+
|
11
|
+
context 'for GET & search request' do
|
12
|
+
it 'doesn`t invoke refresh' do
|
13
|
+
expect(client).to_not receive(:refresh)
|
14
|
+
client.get 1
|
15
|
+
client.search query: {match_all: {}}
|
16
|
+
client.request method: :get, id: :_mapping
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'for POST, PUT & DELETE requests' do
|
21
|
+
it 'invokes refresh after each request' do
|
22
|
+
expect(client).to receive(:refresh).exactly(3).times
|
23
|
+
client.post id: 1
|
24
|
+
client.put_mapping type: {fields: {}}
|
25
|
+
client.delete id: 2
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'invokes refresh after each request, not wrapped in .disable! block' do
|
29
|
+
expect(client).to receive(:refresh).exactly(2).times
|
30
|
+
client.post id: 1
|
31
|
+
described_class.disable! { client.put_mapping type: {fields: {}} }
|
32
|
+
client.delete id: 2
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elastics::Client::Bulk::Builder do
|
4
|
+
let(:instance) { described_class.new }
|
5
|
+
|
6
|
+
describe '#add_action' do
|
7
|
+
context 'if params is hash' do
|
8
|
+
it 'add param as is' do
|
9
|
+
expect { instance.add_action :action, {test: 1} }.
|
10
|
+
to change { instance.actions }.
|
11
|
+
from([]).
|
12
|
+
to([{action: {test: 1}}])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'if params is not a hash' do
|
17
|
+
it 'treats params as id' do
|
18
|
+
expect { instance.add_action :action, 1 }.
|
19
|
+
to change { instance.actions }.
|
20
|
+
from([]).
|
21
|
+
to([{action: {_id: 1}}])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'adds data as is' do
|
26
|
+
expect { instance.add_action :action, {test: 1}, :data }.
|
27
|
+
to change { instance.actions }.
|
28
|
+
from([]).
|
29
|
+
to([{action: {test: 1}}, :data])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Elastics::Client do
|
35
|
+
let(:client) { Elastics::Client.new }
|
36
|
+
|
37
|
+
describe '#bulk' do
|
38
|
+
context 'when no actions added' do
|
39
|
+
it 'should not invoke #request' do
|
40
|
+
expect(client).to_not receive(:request)
|
41
|
+
client.bulk {}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when some actions added' do
|
46
|
+
it 'should invoke request' do
|
47
|
+
expect(client).to receive(:request).with(
|
48
|
+
id: :_bulk,
|
49
|
+
method: :post,
|
50
|
+
index: :index1,
|
51
|
+
body: "{\"delete\":{\"_id\":1}}\n",
|
52
|
+
)
|
53
|
+
client.bulk(index: :index1) { |x| x.delete 1 }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elastics::Client do
|
4
|
+
let(:instance) { described_class.new }
|
5
|
+
let(:index_name) { 'elastics_test' }
|
6
|
+
|
7
|
+
describe '#refresh!' do
|
8
|
+
subject { instance.refresh!(index_name) }
|
9
|
+
|
10
|
+
context 'when index exists' do
|
11
|
+
before { instance.post(index: index_name) }
|
12
|
+
after { instance.delete(index: index_name) }
|
13
|
+
it { should be }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when index does not exist' do
|
17
|
+
it { expect { subject }.to raise_error(Elastics::NotFound) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#refresh' do
|
22
|
+
subject { instance.refresh(index_name) }
|
23
|
+
|
24
|
+
context 'when index exists' do
|
25
|
+
before { instance.post(index: index_name) }
|
26
|
+
after { instance.delete(index: index_name) }
|
27
|
+
it { should be }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when index does not exist' do
|
31
|
+
it { should be_nil }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max Melentiev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -115,11 +115,15 @@ files:
|
|
115
115
|
- lib/elastics/active_record/model_schema.rb
|
116
116
|
- lib/elastics/active_record/search_result.rb
|
117
117
|
- lib/elastics/active_record/tasks_config.rb
|
118
|
+
- lib/elastics/auto_refresh.rb
|
118
119
|
- lib/elastics/capistrano.rb
|
119
120
|
- lib/elastics/client.rb
|
121
|
+
- lib/elastics/client/bulk.rb
|
120
122
|
- lib/elastics/client/cluster.rb
|
121
123
|
- lib/elastics/query_helper.rb
|
122
124
|
- lib/elastics/railtie.rb
|
125
|
+
- lib/elastics/result.rb
|
126
|
+
- lib/elastics/result/search.rb
|
123
127
|
- lib/elastics/tasks.rb
|
124
128
|
- lib/elastics/tasks/config.rb
|
125
129
|
- lib/elastics/tasks/indices.rb
|
@@ -128,7 +132,10 @@ files:
|
|
128
132
|
- lib/elastics/version.rb
|
129
133
|
- lib/elastics/version_manager.rb
|
130
134
|
- lib/tasks/elastics.rake
|
135
|
+
- spec/lib/elastics/auto_refresh_spec.rb
|
136
|
+
- spec/lib/elastics/client/bulk_spec.rb
|
131
137
|
- spec/lib/elastics/client/cluster_spec.rb
|
138
|
+
- spec/lib/elastics/client_spec.rb
|
132
139
|
- spec/spec_helper.rb
|
133
140
|
homepage: http://github.com/printercu/elastics-rb
|
134
141
|
licenses:
|
@@ -155,6 +162,8 @@ signing_key:
|
|
155
162
|
specification_version: 4
|
156
163
|
summary: ElasticSearch client with ActiveRecord integration
|
157
164
|
test_files:
|
165
|
+
- spec/lib/elastics/auto_refresh_spec.rb
|
166
|
+
- spec/lib/elastics/client/bulk_spec.rb
|
158
167
|
- spec/lib/elastics/client/cluster_spec.rb
|
168
|
+
- spec/lib/elastics/client_spec.rb
|
159
169
|
- spec/spec_helper.rb
|
160
|
-
has_rdoc:
|