search_flip 3.0.0 → 4.0.0.beta1
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/.github/workflows/test.yml +34 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +22 -0
- data/README.md +43 -6
- data/UPDATING.md +40 -0
- data/lib/search_flip.rb +2 -1
- data/lib/search_flip/aggregation.rb +2 -2
- data/lib/search_flip/aws_sigv4_plugin.rb +47 -0
- data/lib/search_flip/connection.rb +1 -1
- data/lib/search_flip/criteria.rb +21 -31
- data/lib/search_flip/highlightable.rb +3 -2
- data/lib/search_flip/http_client.rb +8 -10
- data/lib/search_flip/index.rb +6 -2
- data/lib/search_flip/json.rb +4 -9
- data/lib/search_flip/response.rb +6 -7
- data/lib/search_flip/result.rb +45 -19
- data/lib/search_flip/version.rb +1 -1
- data/search_flip.gemspec +2 -2
- data/spec/search_flip/aggregation_spec.rb +17 -17
- data/spec/search_flip/aws_sigv4_plugin_spec.rb +41 -0
- data/spec/search_flip/connection_spec.rb +4 -4
- data/spec/search_flip/criteria_spec.rb +11 -1
- data/spec/search_flip/http_client_spec.rb +17 -0
- data/spec/search_flip/json_spec.rb +31 -0
- data/spec/search_flip/result_spec.rb +26 -3
- metadata +21 -16
- data/.travis.yml +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e231e9ac3434626705696aea544b0ab30a134de6c6773129e779e6ae7adfab4
|
4
|
+
data.tar.gz: 7fe5852eda4d9d73a1a6bfe14e1c6d807bffa08c47c15c137d624dd4050bbcd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec79c30df34f4cfdb9f8afcd25f4d982d1b03461a00af7a9055f4c48d0b5ffc346cccaed178a6e9137d6cd681f538beaf129d449070b44806966c27ea585d112
|
7
|
+
data.tar.gz: 23c9ea04e2d39447a0aaae56f215e3d6cce59c0c67187ba7a9ca18e509e1cbf22dd8dbd52007f4131880a1f97f9fea23e29892f491d5351f39f7b62019afe921
|
@@ -0,0 +1,34 @@
|
|
1
|
+
on: push
|
2
|
+
name: test
|
3
|
+
jobs:
|
4
|
+
test:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
strategy:
|
7
|
+
fail-fast: false
|
8
|
+
matrix:
|
9
|
+
elasticsearch:
|
10
|
+
- plainpicture/elasticsearch:2.4.1_delete-by-query
|
11
|
+
- elasticsearch:5.4
|
12
|
+
- docker.elastic.co/elasticsearch/elasticsearch:6.7.0
|
13
|
+
- docker.elastic.co/elasticsearch/elasticsearch:7.0.0
|
14
|
+
- docker.elastic.co/elasticsearch/elasticsearch:7.9.0
|
15
|
+
ruby:
|
16
|
+
- 2.5
|
17
|
+
- 2.6
|
18
|
+
- 2.7
|
19
|
+
services:
|
20
|
+
elasticsearch:
|
21
|
+
image: ${{ matrix.elasticsearch }}
|
22
|
+
env:
|
23
|
+
discovery.type: single-node
|
24
|
+
ports:
|
25
|
+
- 9200:9200
|
26
|
+
steps:
|
27
|
+
- uses: actions/checkout@v1
|
28
|
+
- uses: actions/setup-ruby@v1
|
29
|
+
with:
|
30
|
+
ruby-version: ${{ matrix.ruby }}
|
31
|
+
- run: bundle
|
32
|
+
- run: sleep 10
|
33
|
+
- run: bundle exec rspec
|
34
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
|
2
2
|
# CHANGELOG
|
3
3
|
|
4
|
+
## v4.0.0
|
5
|
+
|
6
|
+
* [BREAKING] For performance reasons, `SearchFlip::Result` now no longer
|
7
|
+
inherits `Hashie::Mash`
|
8
|
+
* It no longer supports symbol based access like `result[:id]`
|
9
|
+
* It no longer supports question mark methods like `result.title?`
|
10
|
+
* It no longer supports method based assignment like `result.some_key = "value"`
|
11
|
+
|
12
|
+
## v3.1.2
|
13
|
+
|
14
|
+
* Fix ignored false value for source when merging criterias
|
15
|
+
|
16
|
+
## v3.1.1
|
17
|
+
|
18
|
+
* Make `SearchFlip::Result.from_hit` work with the `_source` being disabled
|
19
|
+
|
20
|
+
## v3.1.0
|
21
|
+
|
22
|
+
* Added plugin support in `SearchFlip::HTTPClient`
|
23
|
+
* Added `SearchFlip::AwsSigv4Plugin` to be able to use AWS Elasticsearch with
|
24
|
+
signed requests
|
25
|
+
|
4
26
|
## v3.0.0
|
5
27
|
|
6
28
|
* Added `Criteria#to_query`, which returns a raw query including all queries
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
**Full-Featured Elasticsearch Ruby Client with a Chainable DSL**
|
5
5
|
|
6
|
-
[](https://github.com/mrkamel/search_flip/actions?query=workflow%3Atest+branch%3Amaster)
|
7
7
|
[](http://badge.fury.io/rb/search_flip)
|
8
8
|
|
9
9
|
Using SearchFlip it is dead-simple to create index classes that correspond to
|
@@ -51,8 +51,7 @@ CommentIndex.search("hello world").where(available: true).sort(id: "desc").aggre
|
|
51
51
|
|
52
52
|
```
|
53
53
|
|
54
|
-
Finally, SearchFlip comes with a minimal set of dependencies (http-rb
|
55
|
-
and oj only).
|
54
|
+
Finally, SearchFlip comes with a minimal set of dependencies (http-rb and oj only).
|
56
55
|
|
57
56
|
## Reference Docs
|
58
57
|
|
@@ -475,8 +474,8 @@ end
|
|
475
474
|
```
|
476
475
|
|
477
476
|
Generally, aggregation results returned by Elasticsearch are returned as a
|
478
|
-
`SearchFlip::Result`, which basically is
|
479
|
-
them via:
|
477
|
+
`SearchFlip::Result`, which basically is a Hash with method-like access, such
|
478
|
+
that you can access them via:
|
480
479
|
|
481
480
|
```ruby
|
482
481
|
query.aggregations(:username)["mrkamel"].revenue.value
|
@@ -769,6 +768,41 @@ http_client = http_client.headers(key: "value")
|
|
769
768
|
SearchFlip::Connection.new(base_url: "...", http_client: http_client)
|
770
769
|
```
|
771
770
|
|
771
|
+
## AWS Elasticsearch / Signed Requests
|
772
|
+
|
773
|
+
To use SearchFlip with AWS Elasticsearch and signed requests, you have to add
|
774
|
+
`aws-sdk-core` to your Gemfile and tell SearchFlip to use the
|
775
|
+
`SearchFlip::AwsSigv4Plugin`:
|
776
|
+
|
777
|
+
```ruby
|
778
|
+
require "search_flip/aws_sigv4_plugin"
|
779
|
+
|
780
|
+
MyConnection = SearchFlip::Connection.new(
|
781
|
+
base_url: "https://your-elasticsearch-cluster.es.amazonaws.com",
|
782
|
+
http_client: SearchFlip::HTTPClient.new(
|
783
|
+
plugins: [
|
784
|
+
SearchFlip::AwsSigv4Plugin.new(
|
785
|
+
region: "...",
|
786
|
+
access_key_id: "...",
|
787
|
+
secret_access_key: "..."
|
788
|
+
)
|
789
|
+
]
|
790
|
+
)
|
791
|
+
)
|
792
|
+
```
|
793
|
+
|
794
|
+
Again, in your index you need to specify this connection:
|
795
|
+
|
796
|
+
```ruby
|
797
|
+
class MyIndex
|
798
|
+
include SearchFlip::Index
|
799
|
+
|
800
|
+
def self.connection
|
801
|
+
MyConnection
|
802
|
+
end
|
803
|
+
end
|
804
|
+
```
|
805
|
+
|
772
806
|
## Routing and other index-time options
|
773
807
|
|
774
808
|
Override `index_options` in case you want to use routing or pass other
|
@@ -914,6 +948,10 @@ It uses `after_commit` (if applicable, `after_save`, `after_destroy` and
|
|
914
948
|
`after_touch` otherwise) hooks to synchronously update the index when your
|
915
949
|
model changes.
|
916
950
|
|
951
|
+
## Semantic Versioning
|
952
|
+
|
953
|
+
SearchFlip is using Semantic Versioning: [SemVer](http://semver.org/)
|
954
|
+
|
917
955
|
## Links
|
918
956
|
|
919
957
|
* Elasticsearch: [https://www.elastic.co/](https://www.elastic.co/)
|
@@ -945,5 +983,4 @@ $ rspec
|
|
945
983
|
|
946
984
|
That's it.
|
947
985
|
|
948
|
-
|
949
986
|
[Bulk API]: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
|
data/UPDATING.md
CHANGED
@@ -1,6 +1,46 @@
|
|
1
1
|
|
2
2
|
# Updating from previous SearchFlip versions
|
3
3
|
|
4
|
+
## Update 3.x to 4.x
|
5
|
+
|
6
|
+
**[BREAKING]** For performance reasons, `SearchFlip::Result` no longer
|
7
|
+
inherits `Hashie::Mash`
|
8
|
+
|
9
|
+
* It no longer supports symbol based access like `result[:id]`
|
10
|
+
|
11
|
+
2.x:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
CommentIndex.match_all.results.first[:id]
|
15
|
+
CommentIndex.aggregate(:tags).aggregations(:tags).values.first[:doc_count]
|
16
|
+
```
|
17
|
+
|
18
|
+
3.x
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
CommentIndex.match_all.results.first["id"] # or .id
|
22
|
+
CommentIndex.aggregate(:tags).aggregations(:tags).values.first["doc_count"] # or .doc_count
|
23
|
+
```
|
24
|
+
|
25
|
+
* It no longer supports question mark methods like `result.title?`
|
26
|
+
|
27
|
+
2.x:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
CommentIndex.match_all.results.first.is_published?
|
31
|
+
```
|
32
|
+
|
33
|
+
3.x
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
CommentIndex.match_all.results.first.is_published == true
|
37
|
+
```
|
38
|
+
|
39
|
+
* It no longer supports method based assignment like `result.some_key = "value"`.
|
40
|
+
|
41
|
+
However, this should not have any practical implications, as changing the
|
42
|
+
results is not considered to be a common use case.
|
43
|
+
|
4
44
|
## Update 2.x to 3.x
|
5
45
|
|
6
46
|
* **[BREAKING]** No longer pass multiple arguments to `#must`, `#must_not`,
|
data/lib/search_flip.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require "ruby2_keywords"
|
2
2
|
require "forwardable"
|
3
3
|
require "http"
|
4
|
-
require "hashie"
|
5
4
|
require "thread"
|
6
5
|
require "oj"
|
7
6
|
require "set"
|
@@ -39,6 +38,8 @@ module SearchFlip
|
|
39
38
|
attr_reader :code, :body
|
40
39
|
|
41
40
|
def initialize(code:, body:)
|
41
|
+
super
|
42
|
+
|
42
43
|
@code = code
|
43
44
|
@body = body
|
44
45
|
end
|
@@ -40,7 +40,7 @@ module SearchFlip
|
|
40
40
|
else
|
41
41
|
filters = (filter_values || []) + (must_not_values || []).map { |must_not_value| { not: must_not_value } }
|
42
42
|
queries = must_values ? { must: must_values } : {}
|
43
|
-
filters_and_queries = filters + (queries.size > 0 ? [bool: queries] : [])
|
43
|
+
filters_and_queries = filters + (queries.size > 0 ? [{ bool: queries }] : [])
|
44
44
|
|
45
45
|
res[:filter] = filters_and_queries.size > 1 ? { and: filters_and_queries } : filters_and_queries.first
|
46
46
|
end
|
@@ -101,7 +101,7 @@ module SearchFlip
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def respond_to_missing?(name, *args)
|
104
|
-
target.respond_to?(name, *args)
|
104
|
+
target.respond_to?(name, *args) || super
|
105
105
|
end
|
106
106
|
|
107
107
|
def method_missing(name, *args, &block)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "aws-sdk-core"
|
2
|
+
require "uri"
|
3
|
+
|
4
|
+
module SearchFlip
|
5
|
+
# The SearchFlip::AwsSigV4Plugin is a plugin for the SearchFlip::HTTPClient
|
6
|
+
# to be used with AWS Elasticsearch to sign requests, i.e. add signed
|
7
|
+
# headers, before sending the request to Elasticsearch.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# MyConnection = SearchFlip::Connection.new(
|
11
|
+
# base_url: "https://your-elasticsearch-cluster.es.amazonaws.com",
|
12
|
+
# http_client: SearchFlip::HTTPClient.new(
|
13
|
+
# plugins: [
|
14
|
+
# SearchFlip::AwsSigv4Plugin.new(
|
15
|
+
# region: "...",
|
16
|
+
# access_key_id: "...",
|
17
|
+
# secret_access_key: "..."
|
18
|
+
# )
|
19
|
+
# ]
|
20
|
+
# )
|
21
|
+
# )
|
22
|
+
|
23
|
+
class AwsSigv4Plugin
|
24
|
+
attr_accessor :signer
|
25
|
+
|
26
|
+
def initialize(options = {})
|
27
|
+
self.signer = Aws::Sigv4::Signer.new({ service: "es" }.merge(options))
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(request, method, uri, options = {})
|
31
|
+
full_uri = URI.parse(uri)
|
32
|
+
full_uri.query = URI.encode_www_form(options[:params]) if options[:params]
|
33
|
+
|
34
|
+
signature_request = {
|
35
|
+
http_method: method.to_s.upcase,
|
36
|
+
url: full_uri.to_s
|
37
|
+
}
|
38
|
+
|
39
|
+
signature_request[:body] = options[:body] if options.key?(:body)
|
40
|
+
signature_request[:body] = options[:json].respond_to?(:to_str) ? options[:json] : JSON.generate(options[:json]) if options[:json]
|
41
|
+
|
42
|
+
signature = signer.sign_request(signature_request)
|
43
|
+
|
44
|
+
request.headers(signature.headers)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -71,7 +71,7 @@ module SearchFlip
|
|
71
71
|
.headers(accept: "application/json", content_type: "application/x-ndjson")
|
72
72
|
.post("#{base_url}/_msearch", body: payload)
|
73
73
|
|
74
|
-
raw_response.
|
74
|
+
SearchFlip::JSON.parse(raw_response.to_s)["responses"].map.with_index do |response, index|
|
75
75
|
SearchFlip::Response.new(criterias[index], response)
|
76
76
|
end
|
77
77
|
end
|
data/lib/search_flip/criteria.rb
CHANGED
@@ -44,35 +44,25 @@ module SearchFlip
|
|
44
44
|
other = other.criteria
|
45
45
|
|
46
46
|
fresh.tap do |criteria|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
criteria.must_not_values = (criteria.must_not_values || []) + other.must_not_values if other.must_not_values
|
67
|
-
criteria.filter_values = (criteria.filter_values || []) + other.filter_values if other.filter_values
|
68
|
-
criteria.post_must_values = (criteria.post_must_values || []) + other.post_must_values if other.post_must_values
|
69
|
-
criteria.post_must_not_values = (criteria.post_must_not_values || []) + other.post_must_not_values if other.post_must_not_values
|
70
|
-
criteria.post_filter_values = (criteria.post_filter_values || []) + other.post_filter_values if other.post_filter_values
|
71
|
-
|
72
|
-
criteria.highlight_values = (criteria.highlight_values || {}).merge(other.highlight_values) if other.highlight_values
|
73
|
-
criteria.suggest_values = (criteria.suggest_values || {}).merge(other.suggest_values) if other.suggest_values
|
74
|
-
criteria.custom_value = (criteria.custom_value || {}).merge(other.custom_value) if other.custom_value
|
75
|
-
criteria.aggregation_values = (criteria.aggregation_values || {}).merge(other.aggregation_values) if other.aggregation_values
|
47
|
+
[
|
48
|
+
:profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :offset_value,
|
49
|
+
:limit_value, :scroll_args, :source_value, :preference_value, :search_type_value,
|
50
|
+
:routing_value, :track_total_hits_value, :explain_value
|
51
|
+
].each do |name|
|
52
|
+
criteria.send(:"#{name}=", other.send(name)) unless other.send(name).nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
[
|
56
|
+
:sort_values, :includes_values, :preload_values, :eager_load_values, :must_values,
|
57
|
+
:must_not_values, :filter_values, :post_must_values, :post_must_not_values,
|
58
|
+
:post_filter_values
|
59
|
+
].each do |name|
|
60
|
+
criteria.send(:"#{name}=", (criteria.send(name) || []) + other.send(name)) if other.send(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
[:highlight_values, :suggest_values, :custom_value, :aggregation_values].each do |name|
|
64
|
+
criteria.send(:"#{name}=", (criteria.send(name) || {}).merge(other.send(name))) if other.send(name)
|
65
|
+
end
|
76
66
|
end
|
77
67
|
end
|
78
68
|
|
@@ -576,7 +566,7 @@ module SearchFlip
|
|
576
566
|
end
|
577
567
|
|
578
568
|
def respond_to_missing?(name, *args)
|
579
|
-
target.respond_to?(name, *args)
|
569
|
+
target.respond_to?(name, *args) || super
|
580
570
|
end
|
581
571
|
|
582
572
|
def method_missing(name, *args, &block)
|
@@ -618,7 +608,7 @@ module SearchFlip
|
|
618
608
|
http_request.post("#{target.type_url}/_search", params: request_params, json: request)
|
619
609
|
end
|
620
610
|
|
621
|
-
SearchFlip::Response.new(self, http_response.
|
611
|
+
SearchFlip::Response.new(self, SearchFlip::JSON.parse(http_response.to_s))
|
622
612
|
rescue SearchFlip::ConnectionError, SearchFlip::ResponseError => e
|
623
613
|
raise e unless failsafe_value
|
624
614
|
|
@@ -34,9 +34,10 @@ module SearchFlip
|
|
34
34
|
criteria.highlight_values = (criteria.highlight_values || {}).merge(options)
|
35
35
|
|
36
36
|
hash =
|
37
|
-
|
37
|
+
case fields
|
38
|
+
when Hash
|
38
39
|
fields
|
39
|
-
|
40
|
+
when Array
|
40
41
|
fields.each_with_object({}) { |field, h| h[field] = {} }
|
41
42
|
else
|
42
43
|
{ fields => {} }
|
@@ -1,15 +1,14 @@
|
|
1
1
|
module SearchFlip
|
2
|
-
# @api private
|
3
|
-
#
|
4
2
|
# The SearchFlip::HTTPClient class wraps the http gem, is for internal use
|
5
3
|
# and responsible for the http request/response handling, ie communicating
|
6
4
|
# with Elasticsearch.
|
7
5
|
|
8
6
|
class HTTPClient
|
9
|
-
attr_accessor :request
|
7
|
+
attr_accessor :request, :plugins
|
10
8
|
|
11
|
-
def initialize
|
9
|
+
def initialize(plugins: [])
|
12
10
|
self.request = HTTP
|
11
|
+
self.plugins = plugins
|
13
12
|
end
|
14
13
|
|
15
14
|
class << self
|
@@ -30,17 +29,16 @@ module SearchFlip
|
|
30
29
|
end
|
31
30
|
|
32
31
|
[:get, :post, :put, :delete, :head].each do |method|
|
33
|
-
define_method(method) do
|
34
|
-
execute(method,
|
32
|
+
define_method(method) do |uri, options = {}|
|
33
|
+
execute(method, uri, options)
|
35
34
|
end
|
36
|
-
|
37
|
-
ruby2_keywords method
|
38
35
|
end
|
39
36
|
|
40
37
|
private
|
41
38
|
|
42
|
-
|
43
|
-
|
39
|
+
def execute(method, uri, options = {})
|
40
|
+
final_request = plugins.inject(self) { |res, cur| cur.call(res, method, uri, options) }
|
41
|
+
response = final_request.request.send(method, uri, options)
|
44
42
|
|
45
43
|
raise SearchFlip::ResponseError.new(code: response.code, body: response.body.to_s) unless response.status.success?
|
46
44
|
|
data/lib/search_flip/index.rb
CHANGED
@@ -455,7 +455,9 @@ module SearchFlip
|
|
455
455
|
# @return [Hash] The specified document
|
456
456
|
|
457
457
|
def get(id, params = {})
|
458
|
-
connection.http_client.headers(accept: "application/json").get("#{type_url}/#{id}", params: params)
|
458
|
+
response = connection.http_client.headers(accept: "application/json").get("#{type_url}/#{id}", params: params)
|
459
|
+
|
460
|
+
SearchFlip::JSON.parse(response.to_s)
|
459
461
|
end
|
460
462
|
|
461
463
|
# Retrieves the documents specified by ids from elasticsearch.
|
@@ -471,7 +473,9 @@ module SearchFlip
|
|
471
473
|
# @return [Hash] The raw response
|
472
474
|
|
473
475
|
def mget(request, params = {})
|
474
|
-
connection.http_client.headers(accept: "application/json").post("#{type_url}/_mget", json: request, params: params)
|
476
|
+
response = connection.http_client.headers(accept: "application/json").post("#{type_url}/_mget", json: request, params: params)
|
477
|
+
|
478
|
+
SearchFlip::JSON.parse(response.to_s)
|
475
479
|
end
|
476
480
|
|
477
481
|
# Sends an analyze request to Elasticsearch. Raises
|
data/lib/search_flip/json.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
module SearchFlip
|
2
2
|
class JSON
|
3
|
-
|
4
|
-
mode: :custom,
|
5
|
-
use_to_json: true
|
6
|
-
}
|
7
|
-
|
8
|
-
def self.default_options
|
9
|
-
@default_options
|
3
|
+
def self.generate(obj)
|
4
|
+
Oj.dump(obj, mode: :custom, use_to_json: true)
|
10
5
|
end
|
11
6
|
|
12
|
-
def self.
|
13
|
-
Oj.
|
7
|
+
def self.parse(str)
|
8
|
+
Oj.load(str, mode: :compat)
|
14
9
|
end
|
15
10
|
end
|
16
11
|
end
|
data/lib/search_flip/response.rb
CHANGED
@@ -156,8 +156,7 @@ module SearchFlip
|
|
156
156
|
end
|
157
157
|
|
158
158
|
# Returns the results, ie hits, wrapped in a SearchFlip::Result object
|
159
|
-
# which basically is a
|
160
|
-
# details.
|
159
|
+
# which basically is a Hash with method-like access.
|
161
160
|
#
|
162
161
|
# @example
|
163
162
|
# CommentIndex.search("hello world").results
|
@@ -166,7 +165,7 @@ module SearchFlip
|
|
166
165
|
# @return [Array] An array of results
|
167
166
|
|
168
167
|
def results
|
169
|
-
@results ||= hits["hits"].map { |hit| Result.from_hit(hit) }
|
168
|
+
@results ||= hits["hits"].map { |hit| SearchFlip::Result.from_hit(hit) }
|
170
169
|
end
|
171
170
|
|
172
171
|
# Returns the named sugggetion, if a name is specified or alle suggestions.
|
@@ -304,13 +303,13 @@ module SearchFlip
|
|
304
303
|
|
305
304
|
@aggregations[key] =
|
306
305
|
if response["aggregations"].nil? || response["aggregations"][key].nil?
|
307
|
-
Result.new
|
306
|
+
SearchFlip::Result.new
|
308
307
|
elsif response["aggregations"][key]["buckets"].is_a?(Array)
|
309
|
-
response["aggregations"][key]["buckets"].each_with_object({}) { |bucket, hash| hash[bucket["key"]] = Result.
|
308
|
+
response["aggregations"][key]["buckets"].each_with_object({}) { |bucket, hash| hash[bucket["key"]] = SearchFlip::Result.convert(bucket) }
|
310
309
|
elsif response["aggregations"][key]["buckets"].is_a?(Hash)
|
311
|
-
Result.
|
310
|
+
SearchFlip::Result.convert(response["aggregations"][key]["buckets"])
|
312
311
|
else
|
313
|
-
Result.
|
312
|
+
SearchFlip::Result.convert(response["aggregations"][key])
|
314
313
|
end
|
315
314
|
end
|
316
315
|
end
|
data/lib/search_flip/result.rb
CHANGED
@@ -1,29 +1,55 @@
|
|
1
1
|
module SearchFlip
|
2
|
-
# The SearchFlip::Result class
|
3
|
-
#
|
2
|
+
# The SearchFlip::Result class is a simple Hash, but extended with
|
3
|
+
# method-like access. Keys assigned via methods are stored as strings.
|
4
|
+
#
|
5
|
+
# @example method access
|
6
|
+
# result = SearchFlip::Result.new
|
7
|
+
# result["some_key"] = "value"
|
8
|
+
# result.some_key # => "value"
|
4
9
|
|
5
|
-
class Result <
|
6
|
-
def self.
|
7
|
-
|
8
|
-
end
|
10
|
+
class Result < Hash
|
11
|
+
def self.convert(hash)
|
12
|
+
res = self[hash]
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# SearchFlip::Result.from_hit(top_sales_hits.first)
|
14
|
+
res.each do |key, value|
|
15
|
+
if value.is_a?(Hash)
|
16
|
+
res[key] = convert(value)
|
17
|
+
elsif value.is_a?(Array)
|
18
|
+
res[key] = convert_array(value)
|
19
|
+
end
|
20
|
+
end
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
res
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
def self.convert_array(arr)
|
26
|
+
arr.map do |obj|
|
27
|
+
if obj.is_a?(Hash)
|
28
|
+
convert(obj)
|
29
|
+
elsif obj.is_a?(Array)
|
30
|
+
convert_array(obj)
|
31
|
+
else
|
32
|
+
obj
|
33
|
+
end
|
24
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# rubocop:disable Lint/MissingSuper
|
25
38
|
|
26
|
-
|
39
|
+
def method_missing(name, *args, &block)
|
40
|
+
self[name.to_s]
|
41
|
+
end
|
42
|
+
|
43
|
+
# rubocop:enable Lint/MissingSuper
|
44
|
+
|
45
|
+
def respond_to_missing?(name, include_private = false)
|
46
|
+
key?(name.to_s) || super
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.from_hit(hit)
|
50
|
+
res = convert(hit["_source"] || {})
|
51
|
+
res["_hit"] = convert(self[hit].tap { |hash| hash.delete("_source") })
|
52
|
+
res
|
27
53
|
end
|
28
54
|
end
|
29
55
|
end
|
data/lib/search_flip/version.rb
CHANGED
data/search_flip.gemspec
CHANGED
@@ -20,11 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.post_install_message = <<~MESSAGE
|
22
22
|
Thanks for using search_flip!
|
23
|
-
When upgrading
|
23
|
+
When upgrading major versions, please check out
|
24
24
|
https://github.com/mrkamel/search_flip/blob/master/UPDATING.md
|
25
25
|
MESSAGE
|
26
26
|
|
27
27
|
spec.add_development_dependency "activerecord", ">= 3.0"
|
28
|
+
spec.add_development_dependency "aws-sdk-core"
|
28
29
|
spec.add_development_dependency "bundler"
|
29
30
|
spec.add_development_dependency "factory_bot"
|
30
31
|
spec.add_development_dependency "rake"
|
@@ -34,7 +35,6 @@ Gem::Specification.new do |spec|
|
|
34
35
|
spec.add_development_dependency "timecop"
|
35
36
|
spec.add_development_dependency "webmock"
|
36
37
|
|
37
|
-
spec.add_dependency "hashie"
|
38
38
|
spec.add_dependency "http"
|
39
39
|
spec.add_dependency "oj"
|
40
40
|
spec.add_dependency "ruby2_keywords"
|
@@ -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
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __dir__)
|
2
|
+
require "search_flip/aws_sigv4_plugin"
|
3
|
+
|
4
|
+
RSpec.describe SearchFlip::AwsSigv4Plugin do
|
5
|
+
describe "#call" do
|
6
|
+
subject(:plugin) do
|
7
|
+
SearchFlip::AwsSigv4Plugin.new(
|
8
|
+
region: "us-east-1",
|
9
|
+
access_key_id: "access key",
|
10
|
+
secret_access_key: "secret access key"
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:client) { SearchFlip::HTTPClient.new }
|
15
|
+
|
16
|
+
it "adds the signed headers to the request" do
|
17
|
+
Timecop.freeze Time.parse("2020-01-01 12:00:00 UTC") do
|
18
|
+
expect(client).to receive(:headers).with(
|
19
|
+
"host" => "localhost",
|
20
|
+
"authorization" => /.*/,
|
21
|
+
"x-amz-content-sha256" => /.*/,
|
22
|
+
"x-amz-date" => /20200101T120000Z/
|
23
|
+
)
|
24
|
+
|
25
|
+
plugin.call(client, :get, "http://localhost/index")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "feeds the http method, full url and body to the signer" do
|
30
|
+
signing_request = {
|
31
|
+
http_method: "GET",
|
32
|
+
url: "http://localhost/index?param=value",
|
33
|
+
body: JSON.generate(key: "value")
|
34
|
+
}
|
35
|
+
|
36
|
+
expect(plugin.signer).to receive(:sign_request).with(signing_request).and_call_original
|
37
|
+
|
38
|
+
plugin.call(client, :get, "http://localhost/index", params: { param: "value" }, json: { key: "value" })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -36,10 +36,10 @@ RSpec.describe SearchFlip::Connection do
|
|
36
36
|
it "changes the aliases" do
|
37
37
|
connection = SearchFlip::Connection.new
|
38
38
|
|
39
|
-
connection.update_aliases(actions: [add: { index: "products", alias: "alias1" }])
|
39
|
+
connection.update_aliases(actions: [{ add: { index: "products", alias: "alias1" } }])
|
40
40
|
expect(connection.get_aliases(alias_name: "alias1").keys).to eq(["products"])
|
41
41
|
|
42
|
-
connection.update_aliases(actions: [remove: { index: "products", alias: "alias1" }])
|
42
|
+
connection.update_aliases(actions: [{ remove: { index: "products", alias: "alias1" } }])
|
43
43
|
expect(connection.alias_exists?("alias1")).to eq(false)
|
44
44
|
end
|
45
45
|
end
|
@@ -79,11 +79,11 @@ RSpec.describe SearchFlip::Connection do
|
|
79
79
|
|
80
80
|
expect(connection.alias_exists?(:some_alias)).to eq(false)
|
81
81
|
|
82
|
-
connection.update_aliases(actions: [add: { index: "products", alias: "some_alias" }])
|
82
|
+
connection.update_aliases(actions: [{ add: { index: "products", alias: "some_alias" } }])
|
83
83
|
|
84
84
|
expect(connection.alias_exists?(:some_alias)).to eq(true)
|
85
85
|
ensure
|
86
|
-
connection.update_aliases(actions: [remove: { index: "products", alias: "some_alias" }])
|
86
|
+
connection.update_aliases(actions: [{ remove: { index: "products", alias: "some_alias" } }])
|
87
87
|
end
|
88
88
|
end
|
89
89
|
end
|
@@ -110,6 +110,16 @@ RSpec.describe SearchFlip::Criteria do
|
|
110
110
|
|
111
111
|
expect(criteria1.merge(criteria2).send(method)).to eq("value2")
|
112
112
|
end
|
113
|
+
|
114
|
+
it "handles false values correctly" do
|
115
|
+
criteria1 = SearchFlip::Criteria.new(target: TestIndex)
|
116
|
+
criteria1.send("#{method}=", true)
|
117
|
+
|
118
|
+
criteria2 = SearchFlip::Criteria.new(target: TestIndex)
|
119
|
+
criteria2.send("#{method}=", false)
|
120
|
+
|
121
|
+
expect(criteria1.merge(criteria2).send(method)).to eq(false)
|
122
|
+
end
|
113
123
|
end
|
114
124
|
end
|
115
125
|
|
@@ -1291,7 +1301,7 @@ RSpec.describe SearchFlip::Criteria do
|
|
1291
1301
|
ProductIndex.import create(:product)
|
1292
1302
|
|
1293
1303
|
query = ProductIndex.match_all.explain(true)
|
1294
|
-
expect(query.results.first._hit.key?(
|
1304
|
+
expect(query.results.first._hit.key?("_explanation")).to eq(true)
|
1295
1305
|
end
|
1296
1306
|
end
|
1297
1307
|
|
@@ -39,6 +39,23 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
describe "plugins" do
|
43
|
+
subject do
|
44
|
+
SearchFlip::HTTPClient.new(
|
45
|
+
plugins: [
|
46
|
+
->(request, _method, _uri, _options = {}) { request.headers("First-Header" => "Value") },
|
47
|
+
->(request, _method, _uri, _options = {}) { request.headers("Second-Header" => "Value") }
|
48
|
+
]
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "injects the plugins and uses their result in the request" do
|
53
|
+
stub_request(:get, "http://localhost/path").with(query: { key: "value" }, headers: { "First-Header" => "Value", "Second-Header" => "Value" }).and_return(body: "success")
|
54
|
+
|
55
|
+
expect(subject.get("http://localhost/path", params: { key: "value" }).body.to_s).to eq("success")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
42
59
|
[:via, :basic_auth, :auth].each do |method|
|
43
60
|
describe "##{method}" do
|
44
61
|
it "creates a dupped instance" do
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __dir__)
|
2
|
+
|
3
|
+
RSpec.describe SearchFlip::JSON do
|
4
|
+
describe ".generate" do
|
5
|
+
it "delegates to Oj" do
|
6
|
+
allow(Oj).to receive(:dump)
|
7
|
+
|
8
|
+
payload = { key: "value" }
|
9
|
+
|
10
|
+
described_class.generate(payload)
|
11
|
+
|
12
|
+
expect(Oj).to have_received(:dump).with(payload, mode: :custom, use_to_json: true)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "generates json" do
|
16
|
+
expect(described_class.generate(key: "value")).to eq('{"key":"value"}')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".parse" do
|
21
|
+
it "delegates to Oj" do
|
22
|
+
allow(Oj).to receive(:load)
|
23
|
+
|
24
|
+
payload = '{"key":"value"}'
|
25
|
+
|
26
|
+
described_class.parse(payload)
|
27
|
+
|
28
|
+
expect(Oj).to have_received(:load).with(payload, mode: :compat)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,6 +1,29 @@
|
|
1
1
|
require File.expand_path("../spec_helper", __dir__)
|
2
2
|
|
3
3
|
RSpec.describe SearchFlip::Result do
|
4
|
+
describe ".convert" do
|
5
|
+
it "deeply converts hashes and arrays" do
|
6
|
+
result = described_class.convert("parent" => { "child" => [{ "key1" => "value" }, { "key2" => 3 }] })
|
7
|
+
|
8
|
+
expect(result.parent.child[0].key1).to eq("value")
|
9
|
+
expect(result.parent.child[1].key2).to eq(3)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#method_missing" do
|
14
|
+
it "returns the value of the key equal to the message name" do
|
15
|
+
expect(described_class.convert("some_key" => "value").some_key).to eq("value")
|
16
|
+
expect(described_class.new.some_key).to be_nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#responds_to_missing?" do
|
21
|
+
it "returns true/false if the key equal to the message name is present or not" do
|
22
|
+
expect(described_class.convert("some_key" => nil).respond_to?(:some_key)).to eq(true)
|
23
|
+
expect(described_class.convert("some_key" => nil).respond_to?(:other_key)).to eq(false)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
4
27
|
describe ".from_hit" do
|
5
28
|
it "adds a _hit key into _source and merges the hit keys into it" do
|
6
29
|
result = SearchFlip::Result.from_hit("_score" => 1.0, "_source" => { "name" => "Some name" })
|
@@ -8,10 +31,10 @@ RSpec.describe SearchFlip::Result do
|
|
8
31
|
expect(result).to eq("name" => "Some name", "_hit" => { "_score" => 1.0 })
|
9
32
|
end
|
10
33
|
|
11
|
-
it "
|
12
|
-
result = SearchFlip::Result.from_hit("
|
34
|
+
it "works with the _source being disabled" do
|
35
|
+
result = SearchFlip::Result.from_hit("_id" => 1)
|
13
36
|
|
14
|
-
expect(result.
|
37
|
+
expect(result._hit._id).to eq(1)
|
15
38
|
end
|
16
39
|
end
|
17
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: search_flip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Vetter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: aws-sdk-core
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: factory_bot
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: sqlite3
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: timecop
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -137,13 +137,13 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: webmock
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
|
-
type: :
|
146
|
+
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
@@ -199,9 +199,9 @@ executables: []
|
|
199
199
|
extensions: []
|
200
200
|
extra_rdoc_files: []
|
201
201
|
files:
|
202
|
+
- ".github/workflows/test.yml"
|
202
203
|
- ".gitignore"
|
203
204
|
- ".rubocop.yml"
|
204
|
-
- ".travis.yml"
|
205
205
|
- CHANGELOG.md
|
206
206
|
- Gemfile
|
207
207
|
- LICENSE.txt
|
@@ -212,6 +212,7 @@ files:
|
|
212
212
|
- lib/search_flip.rb
|
213
213
|
- lib/search_flip/aggregatable.rb
|
214
214
|
- lib/search_flip/aggregation.rb
|
215
|
+
- lib/search_flip/aws_sigv4_plugin.rb
|
215
216
|
- lib/search_flip/bulk.rb
|
216
217
|
- lib/search_flip/config.rb
|
217
218
|
- lib/search_flip/connection.rb
|
@@ -238,11 +239,13 @@ files:
|
|
238
239
|
- search_flip.gemspec
|
239
240
|
- spec/delegate_matcher.rb
|
240
241
|
- spec/search_flip/aggregation_spec.rb
|
242
|
+
- spec/search_flip/aws_sigv4_plugin_spec.rb
|
241
243
|
- spec/search_flip/bulk_spec.rb
|
242
244
|
- spec/search_flip/connection_spec.rb
|
243
245
|
- spec/search_flip/criteria_spec.rb
|
244
246
|
- spec/search_flip/http_client_spec.rb
|
245
247
|
- spec/search_flip/index_spec.rb
|
248
|
+
- spec/search_flip/json_spec.rb
|
246
249
|
- spec/search_flip/model_spec.rb
|
247
250
|
- spec/search_flip/null_instrumenter_spec.rb
|
248
251
|
- spec/search_flip/response_spec.rb
|
@@ -255,7 +258,7 @@ licenses:
|
|
255
258
|
metadata: {}
|
256
259
|
post_install_message: |
|
257
260
|
Thanks for using search_flip!
|
258
|
-
When upgrading
|
261
|
+
When upgrading major versions, please check out
|
259
262
|
https://github.com/mrkamel/search_flip/blob/master/UPDATING.md
|
260
263
|
rdoc_options: []
|
261
264
|
require_paths:
|
@@ -267,9 +270,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
267
270
|
version: '0'
|
268
271
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
269
272
|
requirements:
|
270
|
-
- - "
|
273
|
+
- - ">"
|
271
274
|
- !ruby/object:Gem::Version
|
272
|
-
version:
|
275
|
+
version: 1.3.1
|
273
276
|
requirements: []
|
274
277
|
rubygems_version: 3.0.3
|
275
278
|
signing_key:
|
@@ -278,11 +281,13 @@ summary: Full-Featured Elasticsearch Ruby Client with a Chainable DSL
|
|
278
281
|
test_files:
|
279
282
|
- spec/delegate_matcher.rb
|
280
283
|
- spec/search_flip/aggregation_spec.rb
|
284
|
+
- spec/search_flip/aws_sigv4_plugin_spec.rb
|
281
285
|
- spec/search_flip/bulk_spec.rb
|
282
286
|
- spec/search_flip/connection_spec.rb
|
283
287
|
- spec/search_flip/criteria_spec.rb
|
284
288
|
- spec/search_flip/http_client_spec.rb
|
285
289
|
- spec/search_flip/index_spec.rb
|
290
|
+
- spec/search_flip/json_spec.rb
|
286
291
|
- spec/search_flip/model_spec.rb
|
287
292
|
- spec/search_flip/null_instrumenter_spec.rb
|
288
293
|
- spec/search_flip/response_spec.rb
|
data/.travis.yml
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
env:
|
4
|
-
- ES_IMAGE=plainpicture/elasticsearch:2.4.1_delete-by-query
|
5
|
-
- ES_IMAGE=elasticsearch:5.4
|
6
|
-
- ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:6.7.0
|
7
|
-
- ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.0.0
|
8
|
-
- ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.6.0
|
9
|
-
rvm:
|
10
|
-
- ruby-2.5.3
|
11
|
-
- ruby-2.6.2
|
12
|
-
- ruby-2.7.1
|
13
|
-
before_install:
|
14
|
-
- docker-compose up -d
|
15
|
-
- sleep 10
|
16
|
-
install:
|
17
|
-
- travis_retry bundle install
|
18
|
-
script:
|
19
|
-
- bundle exec rspec
|
20
|
-
- bundle exec rubocop
|