chewy 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +35 -29
- data/Appraisals +37 -0
- data/CHANGELOG.md +115 -4
- data/Gemfile +2 -3
- data/README.md +135 -40
- data/chewy.gemspec +4 -3
- data/gemfiles/rails.3.2.activerecord.gemfile +13 -0
- data/gemfiles/rails.3.2.activerecord.kaminari.gemfile +14 -0
- data/gemfiles/rails.3.2.activerecord.will_paginate.gemfile +14 -0
- data/gemfiles/rails.4.0.activerecord.gemfile +13 -0
- data/gemfiles/rails.4.0.activerecord.kaminari.gemfile +14 -0
- data/gemfiles/rails.4.0.activerecord.will_paginate.gemfile +14 -0
- data/gemfiles/rails.4.0.mongoid.gemfile +13 -0
- data/gemfiles/rails.4.0.mongoid.kaminari.gemfile +14 -0
- data/gemfiles/rails.4.0.mongoid.will_paginate.gemfile +14 -0
- data/gemfiles/rails.4.1.activerecord.gemfile +13 -0
- data/gemfiles/rails.4.1.activerecord.kaminari.gemfile +14 -0
- data/gemfiles/rails.4.1.activerecord.will_paginate.gemfile +14 -0
- data/gemfiles/rails.4.1.mongoid.gemfile +13 -0
- data/gemfiles/rails.4.1.mongoid.kaminari.gemfile +14 -0
- data/gemfiles/rails.4.1.mongoid.will_paginate.gemfile +14 -0
- data/gemfiles/rails.4.2.activerecord.gemfile +13 -0
- data/gemfiles/rails.4.2.activerecord.kaminari.gemfile +14 -0
- data/gemfiles/rails.4.2.activerecord.will_paginate.gemfile +14 -0
- data/gemfiles/rails.4.2.mongoid.gemfile +13 -0
- data/gemfiles/rails.4.2.mongoid.kaminari.gemfile +14 -0
- data/gemfiles/rails.4.2.mongoid.will_paginate.gemfile +14 -0
- data/lib/chewy.rb +65 -0
- data/lib/chewy/config.rb +44 -93
- data/lib/chewy/errors.rb +14 -5
- data/lib/chewy/fields/base.rb +8 -7
- data/lib/chewy/fields/root.rb +2 -2
- data/lib/chewy/index.rb +7 -9
- data/lib/chewy/log_subscriber.rb +34 -0
- data/lib/chewy/query.rb +41 -27
- data/lib/chewy/query/criteria.rb +28 -23
- data/lib/chewy/query/scoping.rb +20 -0
- data/lib/chewy/railtie.rb +51 -13
- data/lib/chewy/repository.rb +61 -0
- data/lib/chewy/rspec/update_index.rb +3 -6
- data/lib/chewy/search.rb +28 -7
- data/lib/chewy/strategy.rb +60 -0
- data/lib/chewy/strategy/atomic.rb +31 -0
- data/lib/chewy/strategy/base.rb +27 -0
- data/lib/chewy/strategy/bypass.rb +15 -0
- data/lib/chewy/strategy/urgent.rb +17 -0
- data/lib/chewy/type.rb +19 -5
- data/lib/chewy/type/adapter/active_record.rb +28 -117
- data/lib/chewy/type/adapter/base.rb +35 -0
- data/lib/chewy/type/adapter/mongoid.rb +23 -123
- data/lib/chewy/type/adapter/object.rb +41 -19
- data/lib/chewy/type/adapter/orm.rb +142 -0
- data/lib/chewy/type/import.rb +43 -16
- data/lib/chewy/type/observe.rb +8 -21
- data/lib/chewy/version.rb +1 -1
- data/lib/tasks/chewy.rake +8 -4
- data/spec/chewy/config_spec.rb +20 -97
- data/spec/chewy/fields/base_spec.rb +24 -11
- data/spec/chewy/fields/time_fields_spec.rb +27 -0
- data/spec/chewy/index/settings_spec.rb +2 -1
- data/spec/chewy/index_spec.rb +98 -79
- data/spec/chewy/query/criteria_spec.rb +14 -0
- data/spec/chewy/query_spec.rb +1 -1
- data/spec/chewy/repository_spec.rb +50 -0
- data/spec/chewy/search_spec.rb +100 -0
- data/spec/chewy/strategy_spec.rb +109 -0
- data/spec/chewy/type/adapter/active_record_spec.rb +110 -46
- data/spec/chewy/type/adapter/mongoid_spec.rb +123 -74
- data/spec/chewy/type/adapter/object_spec.rb +51 -34
- data/spec/chewy/type/import_spec.rb +21 -21
- data/spec/chewy/type/observe_spec.rb +26 -29
- data/spec/chewy/type_spec.rb +19 -0
- data/spec/chewy_spec.rb +19 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/support/active_record.rb +2 -1
- data/spec/support/mongoid.rb +29 -38
- metadata +85 -55
- data/gemfiles/Gemfile.rails-3.2.active_record +0 -6
- data/gemfiles/Gemfile.rails-3.2.active_record.kaminari +0 -7
- data/gemfiles/Gemfile.rails-3.2.active_record.will_paginate +0 -7
- data/gemfiles/Gemfile.rails-4.0.active_record +0 -6
- data/gemfiles/Gemfile.rails-4.0.active_record.kaminari +0 -7
- data/gemfiles/Gemfile.rails-4.0.active_record.will_paginate +0 -7
- data/gemfiles/Gemfile.rails-4.0.mongoid +0 -6
- data/gemfiles/Gemfile.rails-4.0.mongoid.kaminari +0 -7
- data/gemfiles/Gemfile.rails-4.0.mongoid.will_paginate +0 -7
- data/gemfiles/Gemfile.rails-4.1.active_record +0 -6
- data/gemfiles/Gemfile.rails-4.1.active_record.kaminari +0 -7
- data/gemfiles/Gemfile.rails-4.1.active_record.will_paginate +0 -7
- data/gemfiles/Gemfile.rails-4.1.mongoid +0 -6
- data/gemfiles/Gemfile.rails-4.1.mongoid.kaminari +0 -7
- data/gemfiles/Gemfile.rails-4.1.mongoid.will_paginate +0 -7
- data/gemfiles/Gemfile.rails-4.2.active_record +0 -6
- data/gemfiles/Gemfile.rails-4.2.active_record.kaminari +0 -7
- data/gemfiles/Gemfile.rails-4.2.active_record.will_paginate +0 -7
- data/gemfiles/Gemfile.rails-4.2.mongoid +0 -6
- data/gemfiles/Gemfile.rails-4.2.mongoid.kaminari +0 -7
- data/gemfiles/Gemfile.rails-4.2.mongoid.will_paginate +0 -7
- data/spec/chewy/index/search_spec.rb +0 -46
data/lib/chewy/type/import.rb
CHANGED
@@ -26,8 +26,9 @@ module Chewy
|
|
26
26
|
|
27
27
|
ActiveSupport::Notifications.instrument 'import_objects.chewy', type: self do |payload|
|
28
28
|
adapter.import(*args, import_options) do |action_objects|
|
29
|
-
indexed_objects = self.root_object.parent_id && fetch_indexed_objects(action_objects.values.flatten
|
29
|
+
indexed_objects = self.root_object.parent_id && fetch_indexed_objects(action_objects.values.flatten)
|
30
30
|
body = bulk_body(action_objects, indexed_objects)
|
31
|
+
|
31
32
|
errors = bulk(bulk_options.merge(body: body)) if body.any?
|
32
33
|
|
33
34
|
fill_payload_import payload, action_objects
|
@@ -76,33 +77,54 @@ module Chewy
|
|
76
77
|
|
77
78
|
def bulk_body(action_objects, indexed_objects = nil)
|
78
79
|
action_objects.inject([]) do |result, (action, objects)|
|
79
|
-
|
80
|
+
method = "#{action}_bulk_entry"
|
81
|
+
result.concat(objects.map { |object| send(method, object, indexed_objects) }.flatten)
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
83
|
-
def
|
85
|
+
def delete_bulk_entry(object, indexed_objects = nil)
|
84
86
|
entry = {}
|
85
87
|
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
if self.root_object.id
|
89
|
+
entry[:_id] = self.root_object.compose_id(object)
|
90
|
+
else
|
91
|
+
entry[:_id] = object.id if object.respond_to?(:id)
|
92
|
+
entry[:_id] ||= object[:id] || object['id'] if object.is_a?(Hash)
|
93
|
+
entry[:_id] ||= object
|
94
|
+
entry[:_id] = entry[:_id].to_s if defined?(BSON) && entry[:_id].is_a?(BSON::ObjectId)
|
95
|
+
end
|
89
96
|
|
90
97
|
if self.root_object.parent_id
|
91
|
-
entry[:
|
98
|
+
existing_object = entry[:_id].present? && indexed_objects && indexed_objects[entry[:_id].to_s]
|
99
|
+
entry.merge!(parent: existing_object[:parent]) if existing_object
|
92
100
|
end
|
93
|
-
|
101
|
+
|
102
|
+
[{ delete: entry }]
|
103
|
+
end
|
104
|
+
|
105
|
+
def index_bulk_entry(object, indexed_objects = nil)
|
106
|
+
entry = {}
|
107
|
+
|
94
108
|
if self.root_object.id
|
95
109
|
entry[:_id] = self.root_object.compose_id(object)
|
110
|
+
else
|
111
|
+
entry[:_id] = object.id if object.respond_to?(:id)
|
112
|
+
entry[:_id] ||= object[:id] || object['id'] if object.is_a?(Hash)
|
113
|
+
entry[:_id] = entry[:_id].to_s if defined?(BSON) && entry[:_id].is_a?(BSON::ObjectId)
|
114
|
+
end
|
115
|
+
entry.delete(:_id) if entry[:_id].blank?
|
116
|
+
|
117
|
+
if self.root_object.parent_id
|
118
|
+
entry[:parent] = self.root_object.compose_parent(object)
|
119
|
+
existing_object = entry[:_id].present? && indexed_objects && indexed_objects[entry[:_id].to_s]
|
96
120
|
end
|
97
121
|
|
98
|
-
|
122
|
+
entry[:data] = object_data(object)
|
99
123
|
|
100
|
-
if
|
101
|
-
[{
|
102
|
-
elsif indexed_object && self.root_object.parent_id && entry[:parent].to_s != indexed_object[:parent]
|
103
|
-
[{ :delete => entry.except(:data).merge(parent: indexed_object[:parent]) }, { action => entry }]
|
124
|
+
if existing_object && entry[:parent].to_s != existing_object[:parent]
|
125
|
+
[{ delete: entry.except(:data).merge(parent: existing_object[:parent]) }, { index: entry }]
|
104
126
|
else
|
105
|
-
[{
|
127
|
+
[{ index: entry }]
|
106
128
|
end
|
107
129
|
end
|
108
130
|
|
@@ -143,9 +165,14 @@ module Chewy
|
|
143
165
|
end.reduce(&:merge) || {}
|
144
166
|
end
|
145
167
|
|
146
|
-
def fetch_indexed_objects(objects
|
168
|
+
def fetch_indexed_objects(objects)
|
147
169
|
ids = objects.map { |object| object.respond_to?(:id) ? object.id : object }
|
148
|
-
result = client.search index:
|
170
|
+
result = client.search index: index_name,
|
171
|
+
type: type_name,
|
172
|
+
fields: '_parent',
|
173
|
+
body: { filter: { ids: { values: ids } } },
|
174
|
+
search_type: 'scan',
|
175
|
+
scroll: '1m'
|
149
176
|
|
150
177
|
indexed_objects = {}
|
151
178
|
|
data/lib/chewy/type/observe.rb
CHANGED
@@ -31,7 +31,7 @@ module Chewy
|
|
31
31
|
method = args.first
|
32
32
|
|
33
33
|
update = Proc.new do
|
34
|
-
clear_association_cache if Chewy.
|
34
|
+
# clear_association_cache if Chewy.strategy.current.name == :urgent
|
35
35
|
|
36
36
|
backreference = if method && method.to_s == 'self'
|
37
37
|
self
|
@@ -44,31 +44,18 @@ module Chewy
|
|
44
44
|
Chewy.derive_type(type_name).update_index(backreference, options)
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
if Chewy.use_after_commit_callbacks
|
48
|
+
after_commit &update
|
49
|
+
else
|
50
|
+
after_save &update
|
51
|
+
after_destroy &update
|
52
|
+
end
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
52
56
|
module ClassMethods
|
53
57
|
def update_index(objects, options = {})
|
54
|
-
|
55
|
-
relation = (defined?(::ActiveRecord) && objects.is_a?(::ActiveRecord::Relation)) ||
|
56
|
-
(defined?(::Mongoid) && objects.is_a?(::Mongoid::Criteria))
|
57
|
-
|
58
|
-
ids = if relation
|
59
|
-
objects.pluck(:id)
|
60
|
-
else
|
61
|
-
Array.wrap(objects).map { |object| object.respond_to?(:id) ? object.id : object.to_i }
|
62
|
-
end
|
63
|
-
|
64
|
-
Chewy.stash self, ids
|
65
|
-
elsif options[:urgent]
|
66
|
-
ActiveSupport::Deprecation.warn("`urgent: true` option is deprecated and will be removed soon, use `Chewy.atomic` block instead")
|
67
|
-
import(objects)
|
68
|
-
elsif Chewy.urgent_update
|
69
|
-
import(objects)
|
70
|
-
end if objects
|
71
|
-
|
58
|
+
Chewy.strategy.current.update(self, objects, options)
|
72
59
|
true
|
73
60
|
end
|
74
61
|
end
|
data/lib/chewy/version.rb
CHANGED
data/lib/tasks/chewy.rake
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
def subscribe_task_stats!
|
2
2
|
ActiveSupport::Notifications.subscribe('import_objects.chewy') do |name, start, finish, id, payload|
|
3
|
-
duration = (
|
4
|
-
puts " Imported #{payload[:type]} for #{duration}s, documents total: #{payload[:import]}"
|
3
|
+
duration = (finish - start).round(2)
|
4
|
+
puts " Imported #{payload[:type]} for #{duration}s, documents total: #{payload[:import].try(:[], :index).to_i}"
|
5
5
|
payload[:errors].each do |action, errors|
|
6
6
|
puts " #{action.to_s.humanize} errors:"
|
7
7
|
errors.each do |error, documents|
|
@@ -13,8 +13,12 @@ def subscribe_task_stats!
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def eager_load_chewy!
|
16
|
-
|
17
|
-
|
16
|
+
dirs = Chewy::Railtie.all_engines.map { |engine| engine.paths['app/chewy'].existent }.flatten.uniq
|
17
|
+
|
18
|
+
dirs.each do |dir|
|
19
|
+
Dir.glob(File.join(dir, '**/*.rb')).each do |file|
|
20
|
+
require_dependency file
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
data/spec/chewy/config_spec.rb
CHANGED
@@ -3,110 +3,33 @@ require 'spec_helper'
|
|
3
3
|
describe Chewy::Config do
|
4
4
|
subject { described_class.send(:new) }
|
5
5
|
|
6
|
+
its(:logger) { should be_nil }
|
7
|
+
its(:transport_logger) { should be_nil }
|
8
|
+
its(:transport_logger) { should be_nil }
|
6
9
|
its(:query_mode) { should == :must }
|
7
10
|
its(:filter_mode) { should == :and }
|
8
11
|
its(:post_filter_mode) { should be_nil }
|
9
|
-
its(:
|
10
|
-
its(:
|
11
|
-
its(:
|
12
|
-
its(:tokenizers) { should == {} }
|
13
|
-
its(:filters) { should == {} }
|
14
|
-
its(:char_filters) { should == {} }
|
15
|
-
|
16
|
-
describe '#analyzer' do
|
17
|
-
specify { expect(subject.analyzer(:name)).to be_nil }
|
18
|
-
|
19
|
-
context do
|
20
|
-
before { subject.analyzer(:name, option: :foo) }
|
21
|
-
specify { expect(subject.analyzer(:name)).to eq({option: :foo}) }
|
22
|
-
specify { expect(subject.analyzers).to eq({name: {option: :foo}}) }
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '#tokenizer' do
|
27
|
-
specify { expect(subject.tokenizer(:name)).to be_nil }
|
28
|
-
|
29
|
-
context do
|
30
|
-
before { subject.tokenizer(:name, option: :foo) }
|
31
|
-
specify { expect(subject.tokenizer(:name)).to eq({option: :foo}) }
|
32
|
-
specify { expect(subject.tokenizers).to eq({name: {option: :foo}}) }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#filter' do
|
37
|
-
specify { expect(subject.filter(:name)).to be_nil }
|
38
|
-
|
39
|
-
context do
|
40
|
-
before { subject.filter(:name, option: :foo) }
|
41
|
-
specify { expect(subject.filter(:name)).to eq({option: :foo}) }
|
42
|
-
specify { expect(subject.filters).to eq({name: {option: :foo}}) }
|
43
|
-
end
|
44
|
-
end
|
12
|
+
its(:root_strategy) { should == :base }
|
13
|
+
its(:request_strategy) { should == :atomic }
|
14
|
+
its(:use_after_commit_callbacks) { should == true }
|
45
15
|
|
46
|
-
describe '#
|
47
|
-
|
16
|
+
describe '#transport_logger=' do
|
17
|
+
let(:logger) { Logger.new('/dev/null') }
|
18
|
+
after { subject.transport_logger = nil }
|
48
19
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
20
|
+
specify { expect { subject.transport_logger = logger }
|
21
|
+
.to change { Chewy.client.transport.logger }.to(logger) }
|
22
|
+
specify { expect { subject.transport_logger = logger }
|
23
|
+
.to change { subject.transport_logger }.to(logger) }
|
54
24
|
end
|
55
25
|
|
56
|
-
describe '#
|
57
|
-
|
58
|
-
|
59
|
-
its(:logger) { should_not be_nil }
|
60
|
-
its(:configuration) { should have_key :logger }
|
61
|
-
end
|
62
|
-
|
63
|
-
describe '#atomic?' do
|
64
|
-
its(:atomic?) { should eq(false) }
|
65
|
-
specify { subject.atomic { expect(subject.atomic?).to eq(true) } }
|
66
|
-
specify { subject.atomic { }; expect(subject.atomic?).to eq(false) }
|
67
|
-
end
|
68
|
-
|
69
|
-
describe '#atomic' do
|
70
|
-
before do
|
71
|
-
stub_index(:dummies) do
|
72
|
-
define_type :dummy
|
73
|
-
end
|
74
|
-
end
|
75
|
-
let(:dummy_type) { DummiesIndex::Dummy }
|
76
|
-
|
77
|
-
specify { expect(subject.atomic { 42 }).to eq(42) }
|
78
|
-
specify { expect { subject.atomic { subject.stash Class.new, 42 } }.to raise_error ArgumentError }
|
79
|
-
specify { subject.atomic { subject.atomic { expect(subject.stash).to eq([{}, {}]) } } }
|
80
|
-
|
81
|
-
specify do
|
82
|
-
expect(dummy_type).to receive(:import).with([1, 2, 3]).once
|
83
|
-
subject.atomic do
|
84
|
-
subject.stash dummy_type, [1, 2]
|
85
|
-
subject.stash dummy_type, [2, 3]
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
specify do
|
90
|
-
expect(dummy_type).to receive(:import).with([1, 2]).once
|
91
|
-
subject.atomic do
|
92
|
-
subject.stash dummy_type, [1, 2]
|
93
|
-
raise
|
94
|
-
end rescue nil
|
95
|
-
end
|
96
|
-
|
97
|
-
specify do
|
98
|
-
expect(dummy_type).to receive(:import).with([2, 3]).once
|
99
|
-
expect(dummy_type).to receive(:import).with([1, 2]).once
|
100
|
-
subject.atomic do
|
101
|
-
subject.stash dummy_type, [2, 3]
|
102
|
-
subject.atomic do
|
103
|
-
subject.stash dummy_type, [1, 2]
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
26
|
+
describe '#transport_tracer=' do
|
27
|
+
let(:logger) { Logger.new('/dev/null') }
|
28
|
+
after { subject.transport_tracer = nil }
|
108
29
|
|
109
|
-
|
110
|
-
|
30
|
+
specify { expect { subject.transport_tracer = logger }
|
31
|
+
.to change { Chewy.client.transport.tracer }.to(logger) }
|
32
|
+
specify { expect { subject.transport_tracer = logger }
|
33
|
+
.to change { subject.transport_tracer }.to(logger) }
|
111
34
|
end
|
112
35
|
end
|
@@ -12,7 +12,7 @@ describe Chewy::Fields::Base do
|
|
12
12
|
|
13
13
|
specify { expect(described_class.new(:name).compose(double(name: 'hello'))).to eq({name: 'hello'}) }
|
14
14
|
|
15
|
-
context do
|
15
|
+
context 'nested fields' do
|
16
16
|
before do
|
17
17
|
field.nested(described_class.new(:subname1, value: ->(o){ o.subvalue1 }))
|
18
18
|
field.nested(described_class.new(:subname2, value: ->{ subvalue2 }))
|
@@ -30,7 +30,22 @@ describe Chewy::Fields::Base do
|
|
30
30
|
]}) }
|
31
31
|
end
|
32
32
|
|
33
|
-
context do
|
33
|
+
context 'parent objects' do
|
34
|
+
let!(:country) { described_class.new(:name, value: ->(country){ country.cities }) }
|
35
|
+
let!(:city) { country.nested(described_class.new(:name, value: ->(city, country) { city.districts.map { |district| [district, country.name] } })) }
|
36
|
+
let!(:district) { city.nested(described_class.new(:name, value: ->(district, city, country) { [district, city.name, country.name] })) }
|
37
|
+
|
38
|
+
specify { expect(country.compose(double(name: 'Thailand', cities: [
|
39
|
+
double(name: 'Bangkok', districts: ['First', 'Second'])
|
40
|
+
]))).to eq(name: [
|
41
|
+
{ 'name' => [
|
42
|
+
{ 'name' => [['First', 'Thailand'], 'Bangkok', 'Thailand'] },
|
43
|
+
{ 'name' => [['Second', 'Thailand'], 'Bangkok', 'Thailand'] }
|
44
|
+
] }
|
45
|
+
]) }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'implicit values' do
|
34
49
|
let(:field) { described_class.new(:name, type: 'string') }
|
35
50
|
before do
|
36
51
|
field.nested(described_class.new(:name))
|
@@ -40,7 +55,7 @@ describe Chewy::Fields::Base do
|
|
40
55
|
specify { expect(field.compose(double(name: 'Alex'))).to eq({name: 'Alex'}) }
|
41
56
|
end
|
42
57
|
|
43
|
-
context do
|
58
|
+
context 'hash values' do
|
44
59
|
let(:field) { described_class.new(:name, type: 'object') }
|
45
60
|
let(:object) { double(name: { key1: 'value1', key2: 'value2' }) }
|
46
61
|
|
@@ -134,7 +149,7 @@ describe Chewy::Fields::Base do
|
|
134
149
|
])).to eq({
|
135
150
|
event: { 'id' => 1, 'category' => [
|
136
151
|
{ 'id' => 2, 'licenses' => { 'id' => 3, 'name' => 'Name1' } },
|
137
|
-
{'id' => 4, 'licenses' => nil }
|
152
|
+
{'id' => 4, 'licenses' => nil.as_json }
|
138
153
|
] }
|
139
154
|
})
|
140
155
|
end
|
@@ -180,7 +195,7 @@ describe Chewy::Fields::Base do
|
|
180
195
|
]))).to eq({
|
181
196
|
event: { 'id' => 1, 'category' => [
|
182
197
|
{ 'id' => 2, 'licenses' => { 'id' => 3, 'name' => 'Name1' } },
|
183
|
-
{'id' => 4, 'licenses' => nil }
|
198
|
+
{'id' => 4, 'licenses' => nil.as_json }
|
184
199
|
] }
|
185
200
|
})
|
186
201
|
end
|
@@ -298,13 +313,11 @@ describe Chewy::Fields::Base do
|
|
298
313
|
|
299
314
|
context 'objects and scopes', :orm do
|
300
315
|
before do
|
301
|
-
stub_model(:city)
|
302
|
-
|
303
|
-
end
|
316
|
+
stub_model(:city)
|
317
|
+
stub_model(:country)
|
304
318
|
|
305
|
-
|
306
|
-
|
307
|
-
end
|
319
|
+
City.belongs_to :country
|
320
|
+
Country.has_many :cities
|
308
321
|
|
309
322
|
stub_index(:countries) do
|
310
323
|
define_type Country do
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Time fields' do
|
4
|
+
before { Chewy.massacre }
|
5
|
+
|
6
|
+
before do
|
7
|
+
stub_index(:posts) do
|
8
|
+
define_type :post do
|
9
|
+
field :published_at, type: 'date'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
before { PostsIndex::Post.import(
|
15
|
+
double(published_at: ActiveSupport::TimeZone[-28800].parse('2014/12/18 18:00')),
|
16
|
+
double(published_at: ActiveSupport::TimeZone[-21600].parse('2014/12/18 20:00')),
|
17
|
+
double(published_at: ActiveSupport::TimeZone[-21600].parse('2014/12/17 20:00')),
|
18
|
+
) }
|
19
|
+
|
20
|
+
let(:time) { ActiveSupport::TimeZone[-14400].parse('2014/12/18 22:00') }
|
21
|
+
let(:range) { (time - 1.minute)..(time + 1.minute) }
|
22
|
+
|
23
|
+
specify { expect(PostsIndex.total).to eq(3) }
|
24
|
+
specify { expect(PostsIndex.filter { published_at == o{range} }.count).to eq(2) }
|
25
|
+
specify { expect(PostsIndex.filter { published_at == o{range.min.utc..range.max.utc} }.count).to eq(2) }
|
26
|
+
specify { expect(PostsIndex.filter { published_at == o{[range.min.to_date..range.max.to_date]} }.count).to eq(1) }
|
27
|
+
end
|
@@ -3,6 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Chewy::Index::Settings do
|
4
4
|
describe '#to_hash' do
|
5
5
|
before { allow(Chewy).to receive_messages(config: Chewy::Config.send(:new)) }
|
6
|
+
before { allow(Chewy).to receive_messages(repository: Chewy::Repository.send(:new)) }
|
6
7
|
|
7
8
|
specify { expect(described_class.new.to_hash).to eq({}) }
|
8
9
|
specify { expect(described_class.new(number_of_nodes: 3).to_hash).to eq({settings: {number_of_nodes: 3}}) }
|
@@ -70,7 +71,7 @@ describe Chewy::Index::Settings do
|
|
70
71
|
.to eq({settings: {index: {number_of_shards: 3}}}) }
|
71
72
|
|
72
73
|
context do
|
73
|
-
before { Chewy.configuration
|
74
|
+
before { allow(Chewy).to receive_messages(configuration: {index: {number_of_shards: 7, number_of_replicas: 2}}) }
|
74
75
|
|
75
76
|
specify { expect(described_class.new.to_hash)
|
76
77
|
.to eq({settings: {index: {number_of_shards: 7, number_of_replicas: 2}}}) }
|
data/spec/chewy/index_spec.rb
CHANGED
@@ -7,6 +7,41 @@ describe Chewy::Index do
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
+
describe '.import', :orm do
|
11
|
+
before do
|
12
|
+
stub_model(:city)
|
13
|
+
stub_model(:country)
|
14
|
+
|
15
|
+
stub_index(:places) do
|
16
|
+
define_type City
|
17
|
+
define_type Country
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let!(:cities) { 2.times.map { |i| City.create! id: i + 1 } }
|
22
|
+
let!(:countries) { 2.times.map { |i| Country.create! id: i + 1 } }
|
23
|
+
|
24
|
+
specify do
|
25
|
+
expect { PlacesIndex.import }.to update_index(PlacesIndex::City).and_reindex(cities)
|
26
|
+
expect { PlacesIndex.import }.to update_index(PlacesIndex::Country).and_reindex(countries)
|
27
|
+
end
|
28
|
+
|
29
|
+
specify do
|
30
|
+
expect { PlacesIndex.import city: cities.first }.to update_index(PlacesIndex::City).and_reindex(cities.first).only
|
31
|
+
expect { PlacesIndex.import city: cities.first }.to update_index(PlacesIndex::Country).and_reindex(countries)
|
32
|
+
end
|
33
|
+
|
34
|
+
specify do
|
35
|
+
expect { PlacesIndex.import city: cities.first, country: countries.last }.to update_index(PlacesIndex::City).and_reindex(cities.first).only
|
36
|
+
expect { PlacesIndex.import city: cities.first, country: countries.last }.to update_index(PlacesIndex::Country).and_reindex(countries.last).only
|
37
|
+
end
|
38
|
+
|
39
|
+
specify do
|
40
|
+
expect(PlacesIndex.client).to receive(:bulk).with(hash_including(refresh: false)).twice
|
41
|
+
PlacesIndex.import city: cities.first, refresh: false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
10
45
|
describe '.client' do
|
11
46
|
specify { expect(stub_index(:dummies1).client).to eq(stub_index(:dummies2).client) }
|
12
47
|
|
@@ -20,28 +55,17 @@ describe Chewy::Index do
|
|
20
55
|
end
|
21
56
|
end
|
22
57
|
|
23
|
-
describe '.
|
24
|
-
|
25
|
-
|
58
|
+
describe '.index_name' do
|
59
|
+
specify { expect { Class.new(Chewy::Index).index_name }.to raise_error Chewy::UndefinedIndex }
|
60
|
+
specify { expect(Class.new(Chewy::Index) { index_name :myindex }.index_name).to eq('myindex') }
|
61
|
+
specify { expect(stub_const('DeveloperIndex', Class.new(Chewy::Index)).index_name).to eq('developer') }
|
62
|
+
specify { expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name).to eq('developers') }
|
26
63
|
|
27
|
-
|
28
|
-
Chewy.
|
29
|
-
|
30
|
-
|
31
|
-
Chewy.filter :names_nysiis, type: 'phonetic', encoder: 'nysiis', replace: false
|
64
|
+
context do
|
65
|
+
before { allow(Chewy).to receive_messages(configuration: {prefix: 'testing'}) }
|
66
|
+
specify { expect(DummiesIndex.index_name).to eq('testing_dummies') }
|
67
|
+
specify { expect(stub_index(:dummies) { index_name :users }.index_name).to eq('testing_users') }
|
32
68
|
end
|
33
|
-
|
34
|
-
let(:documents) { stub_index(:documents) { settings analysis: {analyzer: [:name, :phone, {sorted: {option: :baz}}]} } }
|
35
|
-
|
36
|
-
specify { expect { documents.settings_hash }.to_not change(documents._settings, :inspect) }
|
37
|
-
specify { expect(documents.settings_hash).to eq({settings: {analysis: {
|
38
|
-
analyzer: {name: {filter: ['lowercase', 'icu_folding', 'names_nysiis']},
|
39
|
-
phone: {tokenizer: 'ngram', char_filter: ['phone']},
|
40
|
-
sorted: {option: :baz}},
|
41
|
-
tokenizer: {ngram: {type: 'nGram', min_gram: 3, max_gram: 3}},
|
42
|
-
char_filter: {phone: {type: 'pattern_replace', pattern: '[^\d]', replacement: ''}},
|
43
|
-
filter: {names_nysiis: {type: 'phonetic', encoder: 'nysiis', replace: false}}
|
44
|
-
}}}) }
|
45
69
|
end
|
46
70
|
|
47
71
|
describe '.define_type' do
|
@@ -58,7 +82,6 @@ describe Chewy::Index do
|
|
58
82
|
specify { expect(DummiesIndex.type_hash['country']).to eq(DummiesIndex::Country) }
|
59
83
|
end
|
60
84
|
|
61
|
-
|
62
85
|
context do
|
63
86
|
before { stub_class('City') }
|
64
87
|
before { stub_class('City::District', City) }
|
@@ -102,17 +125,48 @@ describe Chewy::Index do
|
|
102
125
|
specify { expect(DummiesIndex.types(:user)).to be_a Chewy::Query }
|
103
126
|
end
|
104
127
|
|
105
|
-
describe '.
|
106
|
-
|
107
|
-
|
108
|
-
specify { expect(stub_const('DeveloperIndex', Class.new(Chewy::Index)).index_name).to eq('developer') }
|
109
|
-
specify { expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).index_name).to eq('developers') }
|
128
|
+
describe '.settings' do
|
129
|
+
before do
|
130
|
+
allow(Chewy).to receive_messages(config: Chewy::Config.send(:new))
|
110
131
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
132
|
+
Chewy.analyzer :name, filter: ['lowercase', 'icu_folding', 'names_nysiis']
|
133
|
+
Chewy.analyzer :phone, tokenizer: 'ngram', char_filter: ['phone']
|
134
|
+
Chewy.tokenizer :ngram, type: 'nGram', min_gram: 3, max_gram: 3
|
135
|
+
Chewy.char_filter :phone, type: 'pattern_replace', pattern: '[^\d]', replacement: ''
|
136
|
+
Chewy.filter :names_nysiis, type: 'phonetic', encoder: 'nysiis', replace: false
|
137
|
+
end
|
138
|
+
|
139
|
+
let(:documents) { stub_index(:documents) { settings analysis: {analyzer: [:name, :phone, {sorted: {option: :baz}}]} } }
|
140
|
+
|
141
|
+
specify { expect { documents.settings_hash }.to_not change(documents._settings, :inspect) }
|
142
|
+
specify { expect(documents.settings_hash).to eq({settings: {analysis: {
|
143
|
+
analyzer: {name: {filter: ['lowercase', 'icu_folding', 'names_nysiis']},
|
144
|
+
phone: {tokenizer: 'ngram', char_filter: ['phone']},
|
145
|
+
sorted: {option: :baz}},
|
146
|
+
tokenizer: {ngram: {type: 'nGram', min_gram: 3, max_gram: 3}},
|
147
|
+
char_filter: {phone: {type: 'pattern_replace', pattern: '[^\d]', replacement: ''}},
|
148
|
+
filter: {names_nysiis: {type: 'phonetic', encoder: 'nysiis', replace: false}}
|
149
|
+
}}}) }
|
150
|
+
end
|
151
|
+
|
152
|
+
describe '.scopes' do
|
153
|
+
before do
|
154
|
+
stub_index(:places) do
|
155
|
+
def self.by_rating
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.by_name
|
159
|
+
end
|
160
|
+
|
161
|
+
define_type :city do
|
162
|
+
def self.by_id
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
115
166
|
end
|
167
|
+
|
168
|
+
specify { expect(described_class.scopes).to eq([]) }
|
169
|
+
specify { expect(PlacesIndex.scopes).to match_array([:by_rating, :by_name]) }
|
116
170
|
end
|
117
171
|
|
118
172
|
describe '.build_index_name' do
|
@@ -123,24 +177,6 @@ describe Chewy::Index do
|
|
123
177
|
specify { expect(stub_const('DevelopersIndex', Class.new(Chewy::Index)).build_index_name(:users, prefix: 'test', suffix: '2013')).to eq('test_users_2013') }
|
124
178
|
end
|
125
179
|
|
126
|
-
describe '.index_params' do
|
127
|
-
before { allow(Chewy).to receive_messages(config: Chewy::Config.send(:new)) }
|
128
|
-
|
129
|
-
specify { expect(stub_index(:documents).index_params).to eq({}) }
|
130
|
-
specify { expect(stub_index(:documents) { settings number_of_shards: 1 }.index_params.keys).to eq([:settings]) }
|
131
|
-
specify { expect(stub_index(:documents) do
|
132
|
-
define_type :document do
|
133
|
-
field :name, type: 'string'
|
134
|
-
end
|
135
|
-
end.index_params.keys).to eq([:mappings]) }
|
136
|
-
specify { expect(stub_index(:documents) do
|
137
|
-
settings number_of_shards: 1
|
138
|
-
define_type :document do
|
139
|
-
field :name, type: 'string'
|
140
|
-
end
|
141
|
-
end.index_params.keys).to match_array([:mappings, :settings]) }
|
142
|
-
end
|
143
|
-
|
144
180
|
describe '.settings_hash' do
|
145
181
|
before { allow(Chewy).to receive_messages(config: Chewy::Config.send(:new)) }
|
146
182
|
|
@@ -166,38 +202,21 @@ describe Chewy::Index do
|
|
166
202
|
end.mappings_hash[:mappings].keys).to match_array([:document, :document2]) }
|
167
203
|
end
|
168
204
|
|
169
|
-
describe '.
|
170
|
-
before
|
171
|
-
stub_model(:city)
|
172
|
-
stub_model(:country)
|
205
|
+
describe '.index_params' do
|
206
|
+
before { allow(Chewy).to receive_messages(config: Chewy::Config.send(:new)) }
|
173
207
|
|
174
|
-
|
175
|
-
|
176
|
-
|
208
|
+
specify { expect(stub_index(:documents).index_params).to eq({}) }
|
209
|
+
specify { expect(stub_index(:documents) { settings number_of_shards: 1 }.index_params.keys).to eq([:settings]) }
|
210
|
+
specify { expect(stub_index(:documents) do
|
211
|
+
define_type :document do
|
212
|
+
field :name, type: 'string'
|
177
213
|
end
|
178
|
-
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
expect { PlacesIndex.import }.to update_index(PlacesIndex::Country).and_reindex(countries)
|
186
|
-
end
|
187
|
-
|
188
|
-
specify do
|
189
|
-
expect { PlacesIndex.import city: cities.first }.to update_index(PlacesIndex::City).and_reindex(cities.first).only
|
190
|
-
expect { PlacesIndex.import city: cities.first }.to update_index(PlacesIndex::Country).and_reindex(countries)
|
191
|
-
end
|
192
|
-
|
193
|
-
specify do
|
194
|
-
expect { PlacesIndex.import city: cities.first, country: countries.last }.to update_index(PlacesIndex::City).and_reindex(cities.first).only
|
195
|
-
expect { PlacesIndex.import city: cities.first, country: countries.last }.to update_index(PlacesIndex::Country).and_reindex(countries.last).only
|
196
|
-
end
|
197
|
-
|
198
|
-
specify do
|
199
|
-
expect(PlacesIndex.client).to receive(:bulk).with(hash_including(refresh: false)).twice
|
200
|
-
PlacesIndex.import city: cities.first, refresh: false
|
201
|
-
end
|
214
|
+
end.index_params.keys).to eq([:mappings]) }
|
215
|
+
specify { expect(stub_index(:documents) do
|
216
|
+
settings number_of_shards: 1
|
217
|
+
define_type :document do
|
218
|
+
field :name, type: 'string'
|
219
|
+
end
|
220
|
+
end.index_params.keys).to match_array([:mappings, :settings]) }
|
202
221
|
end
|
203
222
|
end
|