search_flip 3.8.0 → 4.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +12 -38
- data/.rubocop.yml +3 -7
- data/CHANGELOG.md +6 -43
- data/Gemfile +1 -15
- data/README.md +39 -53
- data/UPDATING.md +40 -0
- data/docker-compose.yml +0 -1
- data/lib/search_flip/aggregation.rb +1 -1
- data/lib/search_flip/aws_sigv4_plugin.rb +1 -0
- data/lib/search_flip/bulk.rb +2 -2
- data/lib/search_flip/config.rb +1 -7
- data/lib/search_flip/connection.rb +23 -91
- data/lib/search_flip/criteria.rb +10 -37
- data/lib/search_flip/filterable.rb +0 -16
- data/lib/search_flip/http_client.rb +7 -46
- data/lib/search_flip/index.rb +10 -16
- data/lib/search_flip/json.rb +3 -3
- data/lib/search_flip/response.rb +7 -8
- data/lib/search_flip/result.rb +45 -19
- data/lib/search_flip/to_json.rb +29 -1
- data/lib/search_flip/version.rb +1 -1
- data/lib/search_flip.rb +3 -10
- data/search_flip.gemspec +12 -6
- data/spec/search_flip/aggregation_spec.rb +17 -17
- data/spec/search_flip/aws_sigv4_plugin_spec.rb +6 -10
- data/spec/search_flip/bulk_spec.rb +8 -5
- data/spec/search_flip/connection_spec.rb +7 -110
- data/spec/search_flip/criteria_spec.rb +13 -60
- data/spec/search_flip/http_client_spec.rb +3 -13
- data/spec/search_flip/index_spec.rb +13 -34
- data/spec/search_flip/json_spec.rb +4 -18
- data/spec/search_flip/null_instrumenter_spec.rb +2 -2
- data/spec/search_flip/response_spec.rb +2 -2
- data/spec/search_flip/result_spec.rb +23 -6
- data/spec/search_flip/to_json_spec.rb +28 -0
- data/spec/spec_helper.rb +4 -6
- metadata +142 -17
data/lib/search_flip/to_json.rb
CHANGED
@@ -1 +1,29 @@
|
|
1
|
-
|
1
|
+
require "time"
|
2
|
+
require "date"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
class Time
|
6
|
+
def to_json(*args)
|
7
|
+
iso8601(6).to_json
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Date
|
12
|
+
def to_json(*args)
|
13
|
+
iso8601.to_json
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class DateTime
|
18
|
+
def to_json(*args)
|
19
|
+
iso8601(6).to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if defined?(ActiveSupport)
|
24
|
+
class ActiveSupport::TimeWithZone
|
25
|
+
def to_json(*args)
|
26
|
+
iso8601(6).to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/search_flip/version.rb
CHANGED
data/lib/search_flip.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
require "ruby2_keywords"
|
2
2
|
require "forwardable"
|
3
3
|
require "http"
|
4
|
-
require "hashie"
|
5
4
|
require "thread"
|
6
|
-
require "json"
|
7
5
|
require "oj"
|
8
6
|
require "set"
|
9
7
|
|
@@ -33,15 +31,10 @@ require "search_flip/index"
|
|
33
31
|
require "search_flip/model"
|
34
32
|
|
35
33
|
module SearchFlip
|
36
|
-
class
|
34
|
+
class NotSupportedError < StandardError; end
|
35
|
+
class ConnectionError < StandardError; end
|
37
36
|
|
38
|
-
class
|
39
|
-
|
40
|
-
class HttpError < Error; end
|
41
|
-
class ConnectionError < HttpError; end
|
42
|
-
class TimeoutError < HttpError; end
|
43
|
-
|
44
|
-
class ResponseError < Error
|
37
|
+
class ResponseError < StandardError
|
45
38
|
attr_reader :code, :body
|
46
39
|
|
47
40
|
def initialize(code:, body:)
|
data/search_flip.gemspec
CHANGED
@@ -13,12 +13,9 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/mrkamel/search_flip"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
-
spec.metadata["source_code_uri"] = "https://github.com/mrkamel/search_flip"
|
18
|
-
spec.metadata["changelog_uri"] = "https://github.com/mrkamel/search_flip/blob/master/CHANGELOG.md"
|
19
|
-
|
20
16
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
21
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
19
|
spec.require_paths = ["lib"]
|
23
20
|
|
24
21
|
spec.post_install_message = <<~MESSAGE
|
@@ -27,9 +24,18 @@ Gem::Specification.new do |spec|
|
|
27
24
|
https://github.com/mrkamel/search_flip/blob/master/UPDATING.md
|
28
25
|
MESSAGE
|
29
26
|
|
30
|
-
spec.
|
27
|
+
spec.add_development_dependency "activerecord", ">= 3.0"
|
28
|
+
spec.add_development_dependency "aws-sdk-core"
|
29
|
+
spec.add_development_dependency "bundler"
|
30
|
+
spec.add_development_dependency "factory_bot"
|
31
|
+
spec.add_development_dependency "rake"
|
32
|
+
spec.add_development_dependency "rspec"
|
33
|
+
spec.add_development_dependency "rubocop"
|
34
|
+
spec.add_development_dependency "sqlite3"
|
35
|
+
spec.add_development_dependency "timecop"
|
36
|
+
spec.add_development_dependency "webmock"
|
37
|
+
|
31
38
|
spec.add_dependency "http"
|
32
|
-
spec.add_dependency "json"
|
33
39
|
spec.add_dependency "oj"
|
34
40
|
spec.add_dependency "ruby2_keywords"
|
35
41
|
end
|
@@ -15,7 +15,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
15
15
|
aggregation.where(title: "title").where(description: "description").aggregate(:category)
|
16
16
|
end
|
17
17
|
|
18
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
18
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
19
19
|
|
20
20
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
21
21
|
end
|
@@ -36,7 +36,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
36
36
|
.aggregate(:category)
|
37
37
|
end
|
38
38
|
|
39
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
39
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
40
40
|
|
41
41
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
42
42
|
end
|
@@ -54,7 +54,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
54
54
|
aggregation.where(title: "title1".."title3").where(price: 100..200).aggregate(:category)
|
55
55
|
end
|
56
56
|
|
57
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
57
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
58
58
|
|
59
59
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
60
60
|
end
|
@@ -74,7 +74,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
74
74
|
aggregation.where_not(title: "title4").where_not(title: "title5").aggregate(:category)
|
75
75
|
end
|
76
76
|
|
77
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
77
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
78
78
|
|
79
79
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
80
80
|
end
|
@@ -94,7 +94,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
94
94
|
aggregation.where_not(title: ["title1", "title2"]).where_not(title: ["title6", "title7"]).aggregate(:category)
|
95
95
|
end
|
96
96
|
|
97
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
97
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
98
98
|
|
99
99
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
100
100
|
end
|
@@ -114,7 +114,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
114
114
|
aggregation.where_not(price: 100..150).where_not(title: "title6".."title7").aggregate(:category)
|
115
115
|
end
|
116
116
|
|
117
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
117
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
118
118
|
|
119
119
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
120
120
|
end
|
@@ -134,7 +134,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
134
134
|
aggregation.filter(range: { price: { gte: 100, lte: 200 } }).filter(term: { title: "title" }).aggregate(:category)
|
135
135
|
end
|
136
136
|
|
137
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
137
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
138
138
|
|
139
139
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
140
140
|
end
|
@@ -156,7 +156,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
156
156
|
aggregation.range(:price, gte: 100, lte: 200).range(:title, gte: "title1", lte: "title3").aggregate(:category)
|
157
157
|
end
|
158
158
|
|
159
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
159
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
160
160
|
|
161
161
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
162
162
|
end
|
@@ -174,7 +174,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
174
174
|
aggregation.match_all.aggregate(:category)
|
175
175
|
end
|
176
176
|
|
177
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
177
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
178
178
|
|
179
179
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
180
180
|
end
|
@@ -194,7 +194,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
194
194
|
aggregation.exists(:title).exists(:price).aggregate(:category)
|
195
195
|
end
|
196
196
|
|
197
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
197
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
198
198
|
|
199
199
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
200
200
|
end
|
@@ -214,7 +214,7 @@ RSpec.describe SearchFlip::Aggregation do
|
|
214
214
|
aggregation.exists_not(:title).exists_not(:price).aggregate(:category)
|
215
215
|
end
|
216
216
|
|
217
|
-
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket[
|
217
|
+
aggregations = query.aggregations(:category).category.buckets.each_with_object({}) { |bucket, hash| hash[bucket["key"]] = bucket.doc_count }
|
218
218
|
|
219
219
|
expect(aggregations).to eq("category1" => 2, "category2" => 1)
|
220
220
|
end
|
@@ -244,21 +244,21 @@ RSpec.describe SearchFlip::Aggregation do
|
|
244
244
|
expect(aggregations).to eq("category1" => 3, "category2" => 3)
|
245
245
|
|
246
246
|
aggregations = query.aggregations(:category)["category1"].title.buckets.each_with_object({}) do |bucket, hash|
|
247
|
-
hash[bucket[
|
247
|
+
hash[bucket["key"]] = bucket.doc_count
|
248
248
|
end
|
249
249
|
|
250
250
|
expect(aggregations).to eq("title1" => 2, "title2" => 1)
|
251
251
|
|
252
252
|
aggregations = query.aggregations(:category)["category2"].title.buckets.each_with_object({}) do |bucket, hash|
|
253
|
-
hash[bucket[
|
253
|
+
hash[bucket["key"]] = bucket.doc_count
|
254
254
|
end
|
255
255
|
|
256
256
|
expect(aggregations).to eq("title1" => 1, "title2" => 2)
|
257
257
|
|
258
|
-
expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket[
|
259
|
-
expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket[
|
260
|
-
expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[
|
261
|
-
expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[
|
258
|
+
expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket["key"] == "title1" }.price.value).to eq(30)
|
259
|
+
expect(query.aggregations(:category)["category1"].title.buckets.detect { |bucket| bucket["key"] == "title2" }.price.value).to eq(15)
|
260
|
+
expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket["key"] == "title1" }.price.value).to eq(30)
|
261
|
+
expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket["key"] == "title2" }.price.value).to eq(60)
|
262
262
|
end
|
263
263
|
end
|
264
264
|
|
@@ -16,12 +16,10 @@ RSpec.describe SearchFlip::AwsSigv4Plugin do
|
|
16
16
|
it "adds the signed headers to the request" do
|
17
17
|
Timecop.freeze Time.parse("2020-01-01 12:00:00 UTC") do
|
18
18
|
expect(client).to receive(:headers).with(
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
"x-amz-date" => /20200101T120000Z/
|
24
|
-
)
|
19
|
+
"host" => "localhost",
|
20
|
+
"authorization" => /.*/,
|
21
|
+
"x-amz-content-sha256" => /.*/,
|
22
|
+
"x-amz-date" => /20200101T120000Z/
|
25
23
|
)
|
26
24
|
|
27
25
|
plugin.call(client, :get, "http://localhost/index")
|
@@ -29,17 +27,15 @@ RSpec.describe SearchFlip::AwsSigv4Plugin do
|
|
29
27
|
end
|
30
28
|
|
31
29
|
it "feeds the http method, full url and body to the signer" do
|
32
|
-
body = JSON.generate(key: "value")
|
33
|
-
|
34
30
|
signing_request = {
|
35
31
|
http_method: "GET",
|
36
32
|
url: "http://localhost/index?param=value",
|
37
|
-
body:
|
33
|
+
body: JSON.generate(key: "value")
|
38
34
|
}
|
39
35
|
|
40
36
|
expect(plugin.signer).to receive(:sign_request).with(signing_request).and_call_original
|
41
37
|
|
42
|
-
plugin.call(client, :get, "http://localhost/index", params: { param: "value" },
|
38
|
+
plugin.call(client, :get, "http://localhost/index", params: { param: "value" }, json: { key: "value" })
|
43
39
|
end
|
44
40
|
end
|
45
41
|
end
|
@@ -60,15 +60,18 @@ RSpec.describe SearchFlip::Bulk do
|
|
60
60
|
|
61
61
|
it "uses the specified http_client" do
|
62
62
|
product = create(:product)
|
63
|
-
url = ProductIndex.connection.distribution.nil? && ProductIndex.connection.version.to_i < 8 ? ProductIndex.type_url : ProductIndex.index_url
|
64
63
|
|
65
|
-
stub_request(:put, "#{
|
64
|
+
stub_request(:put, "#{ProductIndex.type_url}/_bulk")
|
65
|
+
.with(headers: { "X-Header" => "Value" })
|
66
|
+
.to_return(status: 500)
|
66
67
|
|
67
|
-
|
68
|
-
bulk
|
68
|
+
block = lambda do
|
69
|
+
ProductIndex.bulk http_client: ProductIndex.connection.http_client.headers("X-Header" => "Value") do |bulk|
|
70
|
+
bulk.index product.id, ProductIndex.serialize(product)
|
71
|
+
end
|
69
72
|
end
|
70
73
|
|
71
|
-
expect(
|
74
|
+
expect(&block).to raise_error(SearchFlip::ResponseError)
|
72
75
|
end
|
73
76
|
|
74
77
|
it "transmits up to bulk_max_mb only" do
|
@@ -1,12 +1,6 @@
|
|
1
1
|
require File.expand_path("../spec_helper", __dir__)
|
2
2
|
|
3
3
|
RSpec.describe SearchFlip::Connection do
|
4
|
-
describe "#distribution" do
|
5
|
-
it "reutrns the distribution" do
|
6
|
-
expect([nil, "opensearch"]).to include(SearchFlip::Connection.new.distribution)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
4
|
describe "#version" do
|
11
5
|
it "returns the version" do
|
12
6
|
expect(SearchFlip::Connection.new.version).to match(/\A[0-9.]+\z/)
|
@@ -98,7 +92,7 @@ RSpec.describe SearchFlip::Connection do
|
|
98
92
|
it "returns the specified indices" do
|
99
93
|
connection = SearchFlip::Connection.new
|
100
94
|
|
101
|
-
expect(connection.get_indices.map { |index| index["index"] }.
|
95
|
+
expect(connection.get_indices.map { |index| index["index"] }.to_set).to eq(["comments", "products"].to_set)
|
102
96
|
expect(connection.get_indices("com*").map { |index| index["index"] }).to eq(["comments"])
|
103
97
|
end
|
104
98
|
|
@@ -176,7 +170,7 @@ RSpec.describe SearchFlip::Connection do
|
|
176
170
|
it "freezes the specified index" do
|
177
171
|
connection = SearchFlip::Connection.new
|
178
172
|
|
179
|
-
if connection.
|
173
|
+
if connection.version.to_f >= 6.6
|
180
174
|
begin
|
181
175
|
connection.create_index("index_name")
|
182
176
|
connection.freeze_index("index_name")
|
@@ -193,7 +187,7 @@ RSpec.describe SearchFlip::Connection do
|
|
193
187
|
it "unfreezes the specified index" do
|
194
188
|
connection = SearchFlip::Connection.new
|
195
189
|
|
196
|
-
if connection.
|
190
|
+
if connection.version.to_f >= 6.6
|
197
191
|
begin
|
198
192
|
connection.create_index("index_name")
|
199
193
|
connection.freeze_index("index_name")
|
@@ -247,7 +241,7 @@ RSpec.describe SearchFlip::Connection do
|
|
247
241
|
end
|
248
242
|
|
249
243
|
describe "#update_mapping" do
|
250
|
-
if SearchFlip::Connection.new.
|
244
|
+
if SearchFlip::Connection.new.version.to_i >= 7
|
251
245
|
it "updates the mapping of an index without type name" do
|
252
246
|
begin
|
253
247
|
connection = SearchFlip::Connection.new
|
@@ -268,19 +262,12 @@ RSpec.describe SearchFlip::Connection do
|
|
268
262
|
begin
|
269
263
|
connection = SearchFlip::Connection.new
|
270
264
|
|
271
|
-
mapping = { "properties" => { "id" => { "type" => "long" } } }
|
265
|
+
mapping = { "type_name" => { "properties" => { "id" => { "type" => "long" } } } }
|
272
266
|
|
273
267
|
connection.create_index("index_name")
|
268
|
+
connection.update_mapping("index_name", mapping, type_name: "type_name")
|
274
269
|
|
275
|
-
|
276
|
-
connection.update_mapping("index_name", { "type_name" => mapping }, type_name: "type_name")
|
277
|
-
|
278
|
-
expect(connection.get_mapping("index_name", type_name: "type_name")).to eq("index_name" => { "mappings" => { "type_name" => mapping } })
|
279
|
-
else
|
280
|
-
connection.update_mapping("index_name", mapping)
|
281
|
-
|
282
|
-
expect(connection.get_mapping("index_name")).to eq("index_name" => { "mappings" => mapping })
|
283
|
-
end
|
270
|
+
expect(connection.get_mapping("index_name", type_name: "type_name")).to eq("index_name" => { "mappings" => mapping })
|
284
271
|
ensure
|
285
272
|
connection.delete_index("index_name") if connection.index_exists?("index_name")
|
286
273
|
end
|
@@ -321,96 +308,6 @@ RSpec.describe SearchFlip::Connection do
|
|
321
308
|
end
|
322
309
|
end
|
323
310
|
|
324
|
-
describe "#bulk" do
|
325
|
-
it "imports objects to the specified indices" do
|
326
|
-
connection = SearchFlip::Connection.new
|
327
|
-
|
328
|
-
bulk = proc do
|
329
|
-
connection.bulk do |indexer|
|
330
|
-
indexer.index 1, { id: 1 }, _index: ProductIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
331
|
-
indexer.index 2, { id: 2 }, _index: ProductIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
332
|
-
indexer.index 1, { id: 1 }, _index: CommentIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: CommentIndex.type_name } : {}
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
expect(&bulk).to(change { CommentIndex.total_count }.by(1).and(change { CommentIndex.total_count }.by(1)))
|
337
|
-
end
|
338
|
-
|
339
|
-
it "raises when no index is given" do
|
340
|
-
connection = SearchFlip::Connection.new
|
341
|
-
|
342
|
-
bulk = proc do
|
343
|
-
connection.bulk do |indexer|
|
344
|
-
indexer.index 1, id: 1
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
348
|
-
expect(&bulk).to raise_error(SearchFlip::ResponseError)
|
349
|
-
end
|
350
|
-
|
351
|
-
it "respects options" do
|
352
|
-
connection = SearchFlip::Connection.new
|
353
|
-
|
354
|
-
connection.bulk do |indexer|
|
355
|
-
indexer.index 1, { id: 1 }, _index: ProductIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
356
|
-
indexer.index 2, { id: 2 }, _index: ProductIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
357
|
-
end
|
358
|
-
|
359
|
-
bulk = proc do
|
360
|
-
connection.bulk do |indexer|
|
361
|
-
indexer.index 1, { id: 1 }, _index: ProductIndex.index_name, version: 1, version_type: "external", ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
362
|
-
indexer.index 2, { id: 2 }, _index: ProductIndex.index_name, version: 1, version_type: "external", ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
expect(&bulk).to raise_error(SearchFlip::Bulk::Error)
|
367
|
-
|
368
|
-
bulk = proc do
|
369
|
-
connection.bulk ignore_errors: [409] do |indexer|
|
370
|
-
indexer.index 1, { id: 1 }, _index: ProductIndex.index_name, version: 1, version_type: "external", ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
371
|
-
indexer.index 2, { id: 2 }, _index: ProductIndex.index_name, version: 1, version_type: "external", ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
|
-
expect(&bulk).not_to(change { ProductIndex.total_count })
|
376
|
-
end
|
377
|
-
|
378
|
-
it "passes default options" do
|
379
|
-
allow(SearchFlip::Bulk).to receive(:new)
|
380
|
-
|
381
|
-
connection = SearchFlip::Connection.new
|
382
|
-
|
383
|
-
connection.bulk do |indexer|
|
384
|
-
indexer.index 1, { id: 1 }, _index: ProductIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
385
|
-
end
|
386
|
-
|
387
|
-
expect(SearchFlip::Bulk).to have_received(:new).with(
|
388
|
-
anything,
|
389
|
-
http_client: connection.http_client,
|
390
|
-
bulk_limit: connection.bulk_limit,
|
391
|
-
bulk_max_mb: connection.bulk_max_mb
|
392
|
-
)
|
393
|
-
end
|
394
|
-
|
395
|
-
it "passes custom options" do
|
396
|
-
allow(SearchFlip::Bulk).to receive(:new)
|
397
|
-
|
398
|
-
connection = SearchFlip::Connection.new
|
399
|
-
|
400
|
-
options = {
|
401
|
-
bulk_limit: "bulk limit",
|
402
|
-
bulk_max_mb: "bulk max mb",
|
403
|
-
http_client: "http client"
|
404
|
-
}
|
405
|
-
|
406
|
-
connection.bulk(options) do |indexer|
|
407
|
-
indexer.index 1, { id: 1 }, _index: ProductIndex.index_name, ** connection.distribution.nil? && connection.version.to_i < 8 ? { _type: ProductIndex.type_name } : {}
|
408
|
-
end
|
409
|
-
|
410
|
-
expect(SearchFlip::Bulk).to have_received(:new).with(anything, options)
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
311
|
describe "#index_url" do
|
415
312
|
it "returns the index url for the specified index" do
|
416
313
|
connection = SearchFlip::Connection.new(base_url: "base_url")
|
@@ -97,8 +97,7 @@ RSpec.describe SearchFlip::Criteria do
|
|
97
97
|
methods = [
|
98
98
|
:profile_value, :failsafe_value, :terminate_after_value, :timeout_value,
|
99
99
|
:offset_value, :limit_value, :scroll_args, :source_value, :preference_value,
|
100
|
-
:search_type_value, :routing_value, :track_total_hits_value, :explain_value
|
101
|
-
:http_timeout_value
|
100
|
+
:search_type_value, :routing_value, :track_total_hits_value, :explain_value
|
102
101
|
]
|
103
102
|
|
104
103
|
methods.each do |method|
|
@@ -192,22 +191,6 @@ RSpec.describe SearchFlip::Criteria do
|
|
192
191
|
end
|
193
192
|
end
|
194
193
|
|
195
|
-
describe "#http_timeout" do
|
196
|
-
it "sets the query timeout" do
|
197
|
-
http_client = double("client").as_null_object
|
198
|
-
allow(http_client).to receive(:timeout).and_return(http_client)
|
199
|
-
allow(http_client).to receive(:post).and_raise(SearchFlip::TimeoutError)
|
200
|
-
allow(ProductIndex.connection).to receive(:http_client).and_return(http_client)
|
201
|
-
|
202
|
-
expect { ProductIndex.http_timeout(1).execute }.to raise_error(SearchFlip::TimeoutError)
|
203
|
-
expect(http_client).to have_received(:timeout).with(1)
|
204
|
-
end
|
205
|
-
|
206
|
-
it "executes without errors" do
|
207
|
-
expect { ProductIndex.http_timeout(1).execute }.not_to raise_error
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
194
|
describe "#terminate_after" do
|
212
195
|
it "sets the terminate after value" do
|
213
196
|
query = ProductIndex.terminate_after(1)
|
@@ -433,18 +416,6 @@ RSpec.describe SearchFlip::Criteria do
|
|
433
416
|
end
|
434
417
|
end
|
435
418
|
|
436
|
-
describe "#match_none" do
|
437
|
-
it "does not match any documents" do
|
438
|
-
if ProductIndex.connection.distribution || ProductIndex.connection.version.to_i >= 5
|
439
|
-
ProductIndex.import create(:product)
|
440
|
-
|
441
|
-
query = ProductIndex.match_none
|
442
|
-
|
443
|
-
expect(query.records).to eq([])
|
444
|
-
end
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
419
|
describe "#exists" do
|
449
420
|
it "sets up the constraints correctly and is chainable" do
|
450
421
|
product1 = create(:product, title: "title1", description: "description1")
|
@@ -479,7 +450,7 @@ RSpec.describe SearchFlip::Criteria do
|
|
479
450
|
|
480
451
|
describe "#post_search" do
|
481
452
|
it "sets up the constraints correctly and is chainable" do
|
482
|
-
if ProductIndex.connection.
|
453
|
+
if ProductIndex.connection.version.to_i >= 2
|
483
454
|
product1 = create(:product, title: "title1", category: "category1")
|
484
455
|
product2 = create(:product, title: "title2", category: "category2")
|
485
456
|
product3 = create(:product, title: "title3", category: "category1")
|
@@ -886,7 +857,7 @@ RSpec.describe SearchFlip::Criteria do
|
|
886
857
|
|
887
858
|
describe "#profile" do
|
888
859
|
it "sets up the constraints correctly" do
|
889
|
-
if ProductIndex.connection.
|
860
|
+
if ProductIndex.connection.version.to_i >= 2
|
890
861
|
expect(ProductIndex.profile(true).raw_response["profile"]).not_to be_nil
|
891
862
|
end
|
892
863
|
end
|
@@ -1221,19 +1192,13 @@ RSpec.describe SearchFlip::Criteria do
|
|
1221
1192
|
end
|
1222
1193
|
|
1223
1194
|
describe "#failsafe" do
|
1224
|
-
|
1225
|
-
|
1226
|
-
http_client = double("client").as_null_object
|
1227
|
-
allow(http_client).to receive(:post).and_raise(error)
|
1228
|
-
allow(ProductIndex.connection).to receive(:http_client).and_return(http_client)
|
1229
|
-
|
1230
|
-
expect { ProductIndex.all.execute }.to raise_error(error)
|
1195
|
+
it "prevents query syntax exceptions" do
|
1196
|
+
expect { ProductIndex.search("syntax/error").records }.to raise_error(SearchFlip::ResponseError)
|
1231
1197
|
|
1232
|
-
|
1198
|
+
query = ProductIndex.failsafe(true).search("syntax/error")
|
1233
1199
|
|
1234
|
-
|
1235
|
-
|
1236
|
-
end
|
1200
|
+
expect(query.records).to eq([])
|
1201
|
+
expect(query.total_entries).to eq(0)
|
1237
1202
|
end
|
1238
1203
|
end
|
1239
1204
|
|
@@ -1322,7 +1287,7 @@ RSpec.describe SearchFlip::Criteria do
|
|
1322
1287
|
|
1323
1288
|
describe "#track_total_hits" do
|
1324
1289
|
it "is added to the request" do
|
1325
|
-
if ProductIndex.connection.
|
1290
|
+
if ProductIndex.connection.version.to_i >= 7
|
1326
1291
|
query = ProductIndex.track_total_hits(false)
|
1327
1292
|
|
1328
1293
|
expect(query.request[:track_total_hits]).to eq(false)
|
@@ -1336,7 +1301,7 @@ RSpec.describe SearchFlip::Criteria do
|
|
1336
1301
|
ProductIndex.import create(:product)
|
1337
1302
|
|
1338
1303
|
query = ProductIndex.match_all.explain(true)
|
1339
|
-
expect(query.results.first._hit.key?(
|
1304
|
+
expect(query.results.first._hit.key?("_explanation")).to eq(true)
|
1340
1305
|
end
|
1341
1306
|
end
|
1342
1307
|
|
@@ -1350,40 +1315,28 @@ RSpec.describe SearchFlip::Criteria do
|
|
1350
1315
|
|
1351
1316
|
describe "#preference" do
|
1352
1317
|
it "sets the preference" do
|
1353
|
-
|
1354
|
-
|
1355
|
-
stub_request(:post, "http://127.0.0.1:9200/#{url}/_search?preference=value")
|
1318
|
+
stub_request(:post, "http://127.0.0.1:9200/products/products/_search?preference=value")
|
1356
1319
|
.to_return(status: 200, headers: { content_type: "application/json" }, body: "{}")
|
1357
1320
|
|
1358
1321
|
ProductIndex.preference("value").execute
|
1359
|
-
|
1360
|
-
expect(WebMock).to have_requested(:post, "http://127.0.0.1:9200/#{url}/_search?preference=value")
|
1361
1322
|
end
|
1362
1323
|
end
|
1363
1324
|
|
1364
1325
|
describe "#search_type" do
|
1365
1326
|
it "sets the search_type" do
|
1366
|
-
|
1367
|
-
|
1368
|
-
stub_request(:post, "http://127.0.0.1:9200/#{url}/_search?search_type=value")
|
1327
|
+
stub_request(:post, "http://127.0.0.1:9200/products/products/_search?search_type=value")
|
1369
1328
|
.to_return(status: 200, headers: { content_type: "application/json" }, body: "{}")
|
1370
1329
|
|
1371
1330
|
ProductIndex.search_type("value").execute
|
1372
|
-
|
1373
|
-
expect(WebMock).to have_requested(:post, "http://127.0.0.1:9200/#{url}/_search?search_type=value")
|
1374
1331
|
end
|
1375
1332
|
end
|
1376
1333
|
|
1377
1334
|
describe "#routing" do
|
1378
1335
|
it "sets the search_type" do
|
1379
|
-
|
1380
|
-
|
1381
|
-
stub_request(:post, "http://127.0.0.1:9200/#{url}/_search?routing=value")
|
1336
|
+
stub_request(:post, "http://127.0.0.1:9200/products/products/_search?routing=value")
|
1382
1337
|
.to_return(status: 200, headers: { content_type: "application/json" }, body: "{}")
|
1383
1338
|
|
1384
1339
|
ProductIndex.routing("value").execute
|
1385
|
-
|
1386
|
-
expect(WebMock).to have_requested(:post, "http://127.0.0.1:9200/#{url}/_search?routing=value")
|
1387
1340
|
end
|
1388
1341
|
end
|
1389
1342
|
end
|
@@ -7,7 +7,7 @@ class HttpTestRequest
|
|
7
7
|
self.calls = []
|
8
8
|
end
|
9
9
|
|
10
|
-
[:
|
10
|
+
[:via, :basic_auth, :auth].each do |method|
|
11
11
|
define_method method do |*args|
|
12
12
|
dup.tap do |request|
|
13
13
|
request.calls = calls + [[method, args]]
|
@@ -20,7 +20,7 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
20
20
|
describe "delegation" do
|
21
21
|
subject { SearchFlip::HTTPClient }
|
22
22
|
|
23
|
-
[:headers, :via, :basic_auth, :auth
|
23
|
+
[:headers, :via, :basic_auth, :auth].each do |method|
|
24
24
|
it { should delegate(method).to(:new) }
|
25
25
|
end
|
26
26
|
|
@@ -36,12 +36,6 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
36
36
|
|
37
37
|
expect(SearchFlip::HTTPClient.new.send(method, "http://localhost/path", body: "body", params: { key: "value" }).body.to_s).to eq("success")
|
38
38
|
end
|
39
|
-
|
40
|
-
it "generates json, passes it as body and sets the content type when the json option is used" do
|
41
|
-
stub_request(method, "http://localhost/path").with(body: '{"key":"value"}', headers: { "Content-Type" => "application/json" }).to_return(body: "success")
|
42
|
-
|
43
|
-
expect(SearchFlip::HTTPClient.new.send(method, "http://localhost/path", json: { "key" => "value" }).body.to_s).to eq("success")
|
44
|
-
end
|
45
39
|
end
|
46
40
|
end
|
47
41
|
|
@@ -62,12 +56,8 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
62
56
|
end
|
63
57
|
end
|
64
58
|
|
65
|
-
[:
|
59
|
+
[:via, :basic_auth, :auth].each do |method|
|
66
60
|
describe "##{method}" do
|
67
|
-
it "is understood by HTTP" do
|
68
|
-
expect(HTTP.respond_to?(method)).to eq(true)
|
69
|
-
end
|
70
|
-
|
71
61
|
it "creates a dupped instance" do
|
72
62
|
client = SearchFlip::HTTPClient.new
|
73
63
|
client.request = HttpTestRequest.new
|