stretchy 0.5.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fc1f47df9e733b26cbf7a600076991ef6c2fd740
4
- data.tar.gz: f62cabd7fc16980276d70de66c90dba0d25fb03e
2
+ SHA256:
3
+ metadata.gz: 76d1eeb5c2be5aad546eed305e53d83ea4c64dd9c61e9b40a64ec0246de6c4cf
4
+ data.tar.gz: 4a6ddb55f798e90fde4ce5a1a5cb2b39559ca0eb2b5f9f92f353b0c108dfe224
5
5
  SHA512:
6
- metadata.gz: 0642e6ceab6cb04e30aef51cfedefbc1ae4b49f49b387528f71425d7a72bd9bf21a0763f6e1968e95c4568cc9d9148a66f5565cc42b0e5802adfbf08d6c7d6e7
7
- data.tar.gz: 33e7884e2d19d7dbc269258b21b3cb448b8174e055c0f88338ef786caad83efc38886be1386ec3d094b96b4fed584ab7754bb3f2d7c239fd7d8a838f13be9b35
6
+ metadata.gz: 58dd985f4bdee6edd189c6b5235d2cb59dd96a79c479fae3abae7f88a087f10c383e4c4eb183090c49c9619b2bc5dddad5ad8fdc6f80efc6a507be1dd8de609f
7
+ data.tar.gz: 055776e2bfb69e791c631df6576ed33c76337d74e64720c9ec86e8e79500248d2c37f2104f820aa32c978ee4ee6280dbfc5a9f54c8cfa809465456ee9401c97a
data/.rubocop.yml ADDED
@@ -0,0 +1,260 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2015-12-09 14:43:24 -0800 using RuboCop version 0.32.1.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
8
+ # Offense count: 1
9
+ # Cop supports --auto-correct.
10
+ Lint/BlockAlignment:
11
+ Enabled: false
12
+
13
+ # Offense count: 3
14
+ # Cop supports --auto-correct.
15
+ # Configuration parameters: AlignWith, SupportedStyles, AutoCorrect.
16
+ Lint/EndAlignment:
17
+ Enabled: false
18
+
19
+ # Offense count: 1
20
+ Lint/HandleExceptions:
21
+ Enabled: false
22
+
23
+ # Offense count: 3
24
+ # Cop supports --auto-correct.
25
+ Lint/UnusedBlockArgument:
26
+ Enabled: true
27
+
28
+ # Offense count: 2
29
+ Lint/UselessAssignment:
30
+ Enabled: true
31
+
32
+ # Offense count: 5
33
+ Metrics/AbcSize:
34
+ Max: 15
35
+
36
+ # Offense count: 2
37
+ # Configuration parameters: CountComments.
38
+ Metrics/ClassLength:
39
+ Max: 250
40
+
41
+ # Offense count: 1
42
+ Metrics/CyclomaticComplexity:
43
+ Max: 7
44
+
45
+ # Offense count: 3
46
+ # Configuration parameters: AllowURI, URISchemes.
47
+ Metrics/LineLength:
48
+ Max: 80
49
+
50
+ # Offense count: 8
51
+ # Configuration parameters: CountComments.
52
+ Metrics/MethodLength:
53
+ Max: 20
54
+
55
+ # Offense count: 2
56
+ # Configuration parameters: CountComments.
57
+ Metrics/ModuleLength:
58
+ Max: 250
59
+
60
+ # Offense count: 14
61
+ # Cop supports --auto-correct.
62
+ Style/Alias:
63
+ Enabled: false
64
+
65
+ # Offense count: 1
66
+ # Cop supports --auto-correct.
67
+ # Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle, SupportedLastArgumentHashStyles.
68
+ Style/AlignHash:
69
+ Enabled: false
70
+
71
+ # Offense count: 7
72
+ # Cop supports --auto-correct.
73
+ # Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
74
+ Style/BlockDelimiters:
75
+ Enabled: false
76
+
77
+ # Offense count: 3
78
+ # Cop supports --auto-correct.
79
+ Style/BlockEndNewline:
80
+ Enabled: false
81
+
82
+ # Offense count: 3
83
+ # Cop supports --auto-correct.
84
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
85
+ Style/BracesAroundHashParameters:
86
+ Enabled: false
87
+
88
+ # Offense count: 1
89
+ # Cop supports --auto-correct.
90
+ Style/ClosingParenthesisIndentation:
91
+ Enabled: false
92
+
93
+ # Offense count: 18
94
+ Style/Documentation:
95
+ Enabled: false
96
+
97
+ # Offense count: 3
98
+ Style/DoubleNegation:
99
+ Enabled: false
100
+
101
+ # Offense count: 5
102
+ # Cop supports --auto-correct.
103
+ Style/ElseAlignment:
104
+ Enabled: false
105
+
106
+ # Offense count: 16
107
+ # Cop supports --auto-correct.
108
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
109
+ Style/EmptyLinesAroundBlockBody:
110
+ Enabled: false
111
+
112
+ # Offense count: 6
113
+ # Cop supports --auto-correct.
114
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
115
+ Style/EmptyLinesAroundClassBody:
116
+ Enabled: false
117
+
118
+ # Offense count: 6
119
+ # Cop supports --auto-correct.
120
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
121
+ Style/EmptyLinesAroundModuleBody:
122
+ Enabled: false
123
+
124
+ # Offense count: 4
125
+ # Cop supports --auto-correct.
126
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
127
+ Style/FirstParameterIndentation:
128
+ Enabled: false
129
+
130
+ # Offense count: 1
131
+ # Cop supports --auto-correct.
132
+ # Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues.
133
+ Style/HashSyntax:
134
+ Enabled: false
135
+
136
+ # Offense count: 16
137
+ # Cop supports --auto-correct.
138
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
139
+ Style/IndentHash:
140
+ Enabled: false
141
+
142
+ # Offense count: 18
143
+ # Cop supports --auto-correct.
144
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
145
+ Style/IndentationConsistency:
146
+ Enabled: false
147
+
148
+ # Offense count: 3
149
+ # Cop supports --auto-correct.
150
+ # Configuration parameters: Width.
151
+ Style/IndentationWidth:
152
+ Enabled: false
153
+
154
+ # Offense count: 1
155
+ # Cop supports --auto-correct.
156
+ Style/LineEndConcatenation:
157
+ Enabled: false
158
+
159
+ # Offense count: 3
160
+ # Cop supports --auto-correct.
161
+ Style/MultilineBlockLayout:
162
+ Enabled: false
163
+
164
+ # Offense count: 10
165
+ # Cop supports --auto-correct.
166
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
167
+ Style/MultilineOperationIndentation:
168
+ Enabled: false
169
+
170
+ # Offense count: 2
171
+ # Cop supports --auto-correct.
172
+ # Configuration parameters: PreferredDelimiters.
173
+ Style/PercentLiteralDelimiters:
174
+ Enabled: false
175
+
176
+ # Offense count: 1
177
+ # Configuration parameters: NamePrefix, NamePrefixBlacklist.
178
+ Style/PredicateName:
179
+ Enabled: false
180
+
181
+ # Offense count: 3
182
+ # Configuration parameters: SupportedStyles.
183
+ Style/RaiseArgs:
184
+ EnforcedStyle: compact
185
+
186
+ # Offense count: 1
187
+ # Cop supports --auto-correct.
188
+ Style/RedundantSelf:
189
+ Enabled: false
190
+
191
+ # Offense count: 4
192
+ # Cop supports --auto-correct.
193
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
194
+ Style/SignalException:
195
+ Enabled: false
196
+
197
+ # Offense count: 4
198
+ # Cop supports --auto-correct.
199
+ Style/SingleSpaceBeforeFirstArg:
200
+ Enabled: false
201
+
202
+ # Offense count: 9
203
+ # Cop supports --auto-correct.
204
+ Style/SpaceAfterComma:
205
+ Enabled: false
206
+
207
+ # Offense count: 6
208
+ # Cop supports --auto-correct.
209
+ # Configuration parameters: MultiSpaceAllowedForOperators.
210
+ Style/SpaceAroundOperators:
211
+ Enabled: false
212
+
213
+ # Offense count: 5
214
+ # Cop supports --auto-correct.
215
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
216
+ Style/SpaceBeforeBlockBraces:
217
+ Enabled: false
218
+
219
+ # Offense count: 1
220
+ # Cop supports --auto-correct.
221
+ Style/SpaceBeforeSemicolon:
222
+ Enabled: false
223
+
224
+ # Offense count: 25
225
+ # Cop supports --auto-correct.
226
+ # Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
227
+ Style/SpaceInsideBlockBraces:
228
+ Enabled: false
229
+
230
+ # Offense count: 145
231
+ # Cop supports --auto-correct.
232
+ # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles.
233
+ Style/SpaceInsideHashLiteralBraces:
234
+ Enabled: false
235
+
236
+ # Offense count: 33
237
+ # Cop supports --auto-correct.
238
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
239
+ Style/StringLiterals:
240
+ Enabled: false
241
+
242
+ # Offense count: 1
243
+ # Cop supports --auto-correct.
244
+ # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
245
+ Style/TrivialAccessors:
246
+ Enabled: false
247
+
248
+ # Offense count: 2
249
+ # Cop supports --auto-correct.
250
+ Style/UnneededPercentQ:
251
+ Enabled: false
252
+
253
+ # Align with the style guide.
254
+ Style/CollectionMethods:
255
+ PreferredMethods:
256
+ collect: 'map'
257
+ collect!: 'map!'
258
+ inject: 'reduce'
259
+ detect: 'find'
260
+ find_all: 'select'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.2.2
1
+ 2.4.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org/), although
4
+ "minor" (0.x) changes will include breaking changes until a stable 1.0 release.
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.6.0] - 2015-12-15
9
+ ### Changed
10
+
11
+ * [FEATURE] compatible with [new query / filter contexts](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html) for Elasticsearch 2.0+
12
+
data/Dockerfile ADDED
@@ -0,0 +1,12 @@
1
+ FROM ruby:slim
2
+ RUN apt-get update -qq && apt-get install -y \
3
+ git \
4
+ build-essential \
5
+ libpq-dev \
6
+ curl
7
+ RUN gem install bundler
8
+ RUN mkdir /stretchy
9
+ WORKDIR /stretchy
10
+ ADD . /stretchy
11
+ RUN bundle install
12
+
data/README.md CHANGED
@@ -52,7 +52,7 @@ Stretchy.client = Elasticsearch::Client.new
52
52
 
53
53
  ```ruby
54
54
  # returns a Stretchy::API object
55
- api = Stretchy.query(index: 'myapp_development', type: 'model_name')
55
+ api = Stretchy.query(index: 'myapp_development')
56
56
  ```
57
57
 
58
58
  From here, you can chain the methods to build your desired query.
@@ -219,7 +219,7 @@ Performs a query for the given string anywhere in the document. At least one of
219
219
  api = api.more_like(ids: [1, 2, 3])
220
220
  .more_like(docs: other_search.results)
221
221
  .more_like(
222
- like_text: 'puppies and kittens are great',
222
+ like: 'puppies and kittens are great',
223
223
  fields: ['about_me']
224
224
  )
225
225
  ```
@@ -436,7 +436,7 @@ Included in the Results object for Kaminari compatibility.
436
436
 
437
437
  ## Development
438
438
 
439
- After checking out the repo, run `bundle install` to install dependencies. Then, run `pry` for an interactive prompt that will allow you to experiment.
439
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `pry` for an interactive prompt that will allow you to experiment. Run specs with `rspec`
440
440
 
441
441
  ## Contributing
442
442
 
data/Rakefile CHANGED
@@ -13,8 +13,8 @@ namespace :fixtures do
13
13
  task :gen do
14
14
  require 'json'
15
15
 
16
- q = Stretchy.query(index: 'stretchy_test', type: 'game_dev')
17
- .match(_all: 'game')
16
+ q = Stretchy.query(index: 'stretchy_test')
17
+ .multi_match(query: 'game')
18
18
  .where(url_slug: [
19
19
  'masahiro-sakurai',
20
20
  'tetsuya-mizuguchi',
@@ -0,0 +1,24 @@
1
+ version: '2'
2
+ services:
3
+ elastictwo:
4
+ image: elasticsearch:2-alpine
5
+ elasticfive:
6
+ image: elasticsearch:5-alpine
7
+ testtwo:
8
+ build: .
9
+ command: bundle exec rake
10
+ environment:
11
+ ELASTICSEARCH_URL: 'elastictwo:9200'
12
+ volumes:
13
+ - .:/stretchy
14
+ links:
15
+ - elastictwo
16
+ testfive:
17
+ build: .
18
+ command: bundle exec rake
19
+ environment:
20
+ ELASTICSEARCH_URL: 'elasticfive:9200'
21
+ volumes:
22
+ - .:/stretchy
23
+ links:
24
+ - elastictwo
@@ -22,138 +22,65 @@ module Stretchy
22
22
  end
23
23
 
24
24
  def node
25
- @node ||= if boost_nodes.any?
25
+ @node ||= if function_score_node?
26
26
  function_score_node
27
- elsif filter_nodes.any?
28
- filtered_query_node
29
27
  elsif query_nodes.any?
30
- single_query_node
28
+ query_node
31
29
  else
32
30
  Node.new({match_all: {}}, context)
33
31
  end
34
32
  end
35
33
 
36
34
  def query_nodes
37
- @query_nodes ||= collect_nodes nodes do |n|
38
- n.context?(:query) &&
39
- !n.context?(:boost) &&
40
- !n.context?(:filter)
41
- end
42
- end
43
-
44
- def filter_node
45
- @filter_node ||= if query_nodes.any?
46
- if boost_nodes.any?
47
- Node.new({query: function_score_node.json}, context)
48
- elsif filter_nodes.any?
49
- Node.new({query: filtered_query_node.json}, context)
50
- else
51
- Node.new({query: single_query_node.json}, context)
52
- end
53
- else
54
- Node.new(compile_nodes(filter_nodes).json, context)
55
- end
56
- end
57
-
58
- def filter_json
59
- filter_node.json
35
+ @query_nodes ||= nodes.reject {|n| n.context? :boost }
60
36
  end
61
37
 
62
- def filter_nodes
63
- @filter_nodes ||= begin
64
- node_arr = collect_nodes nodes do |n|
65
- n.context?(:filter) &&
66
- !n.context?(:query) &&
67
- !n.context?(:boost)
68
- end
69
- node_arr += Array(compile_query_filter_node)
70
- node_arr.compact
71
- end
72
- end
73
-
74
- def query_filter_nodes
75
- @query_filter_nodes ||= collect_nodes nodes do |n|
76
- n.context?(:filter) &&
77
- n.context?(:query) &&
78
- !n.context?(:boost)
79
- end
38
+ def boost_nodes
39
+ @boost_nodes ||= nodes.select {|n| n.context? :boost }
80
40
  end
81
41
 
82
- def boost_nodes
83
- @boost_nodes ||= collect_nodes nodes do |n|
84
- n.context?(:boost)
85
- end
42
+ def function_score_node?
43
+ boost_nodes.reject { |n| n.empty? }.any?
86
44
  end
87
45
 
88
46
  private
89
47
 
90
- def collect_nodes(node_arr)
91
- coll = []
92
- node_arr.each do |n|
93
- next unless yield(n)
94
-
95
- if n.respond_to? :node
96
- coll << Node.new(n.node.json, n.context)
97
- else
98
- coll << n
99
- end
48
+ def query_node
49
+ if query_nodes.size > 1 || multicontext?(query_nodes)
50
+ compile_bool query_nodes
51
+ else
52
+ query_nodes.first
100
53
  end
101
- coll.compact
102
54
  end
103
55
 
104
- def compile_nodes(node_arr)
105
- if node_arr.size > 1 ||
106
- node_arr.any?{|n| n.context?(:must_not) || n.context?(:should)}
107
-
108
- compile_bool(node_arr)
109
- else
110
- node_arr.first
111
- end
56
+ def multicontext?(node_arr)
57
+ Array(node_arr).any? {|n| n.context?(:must_not) || n.context?(:should) }
112
58
  end
113
59
 
114
60
  def compile_bool(bool_nodes)
115
61
  split_nodes = split_nodes_for_bool(bool_nodes)
116
- bool_json = {}
117
- if split_nodes[:should_not].size > 0
118
- bool_json[:should] = [
119
- {
120
- bool: {
121
- must: split_nodes[:should].map(&:as_json),
122
- must_not: split_nodes[:should_not].map(&:as_json)
123
- }
124
- }
125
- ]
126
- else
127
- bool_json[:should] = split_nodes[:should].map(&:as_json)
62
+ refined = bool_ctx.each_with_object(split_nodes) do |k, hash|
63
+ hash[k] = Array(compile_bool(hash[k])) if multicontext? hash[k]
128
64
  end
129
- bool_json[:must_not] = split_nodes[:must_not].map(&:as_json)
130
- bool_json[:must] = split_nodes[:must].map(&:as_json)
65
+ bool_json = Hash[refined.map{|k,v| [k, v.map(&:as_json)] }]
131
66
  Node.new(bool: bool_json)
132
67
  end
133
68
 
69
+ def bool_ctx
70
+ [:filter, :must_not, :should]
71
+ end
72
+
134
73
  def split_nodes_for_bool(bool_nodes)
135
- split_nodes = {must: [], must_not: [], should: [], should_not: []}
136
- bool_nodes.each do |n|
137
- if n.context?(:should)
138
- if n.context?(:must_not)
139
- split_nodes[:should_not] << n
140
- else
141
- split_nodes[:should] << n
142
- end
143
- else
144
- if n.context?(:must_not)
145
- split_nodes[:must_not] << n
146
- else
147
- split_nodes[:must] << n
148
- end
149
- end
74
+ bool_nodes.each_with_object({}) do |n, hash|
75
+ key = bool_ctx.find{|c| n.context? c } || :must
76
+ hash[key] ||= []
77
+ hash[key] << Node.new(n.json, n.context.merge(key => nil))
150
78
  end
151
- split_nodes
152
79
  end
153
80
 
154
81
  def compile_boost_functions
155
82
  boost_nodes.map do |n|
156
- next unless n.json.any?
83
+ next if n.empty?
157
84
  n.json
158
85
  end.compact
159
86
  end
@@ -164,36 +91,13 @@ module Stretchy
164
91
  end
165
92
  end
166
93
 
167
- def compile_query_filter_node
168
- compiled = compile_nodes(query_filter_nodes)
169
- Node.new(query: compiled.json) if compiled
170
- end
171
-
172
94
  def function_score_node
173
95
  function_score_json = compile_function_score_options
174
96
  function_score_json[:functions] = compile_boost_functions
175
-
176
- if query_nodes.any?
177
- function_score_json[:query] = filtered_query_node.json
178
- elsif filter_nodes.any?
179
- function_score_json[:filter] = filter_node.json
180
- end
97
+ function_score_json[:query] = query_node.json if query_nodes.any?
181
98
 
182
99
  Node.new({function_score: function_score_json}, context)
183
100
  end
184
101
 
185
- def filtered_query_node
186
- filtered_json = {}
187
- q = compile_nodes(query_nodes)
188
- f = compile_nodes(filter_nodes)
189
- filtered_json[:query] = q.json if q
190
- filtered_json[:filter] = f.json if f
191
- Node.new({filtered: filtered_json}, context)
192
- end
193
-
194
- def single_query_node
195
- Node.new(compile_nodes(query_nodes).json, context)
196
- end
197
-
198
102
  end
199
103
  end
data/lib/stretchy/api.rb CHANGED
@@ -11,19 +11,11 @@ module Stretchy
11
11
 
12
12
  attr_reader :collector, :opts, :root, :body, :context
13
13
 
14
+ delegate [:with_context, :json, :as_json] => :collector
15
+
14
16
  delegate [
15
- :total,
16
- :total_count,
17
- :length,
18
- :size,
19
- :total_pages,
20
- :results,
21
- :hits,
22
- :to_a,
23
- :ids,
24
- :scores,
25
- :explanations,
26
- :aggregations
17
+ :total, :total_count, :length, :size, :total_pages, :results, :hits,
18
+ :to_a, :ids, :scores, :explanations, :aggregations, :each
27
19
  ] => :results_obj
28
20
 
29
21
  def initialize(opts = {})
@@ -74,9 +66,11 @@ module Stretchy
74
66
  end
75
67
 
76
68
  def fields(*list)
77
- add_root fields: list
69
+ add_root _source: list
78
70
  end
79
71
 
72
+ alias :source :fields
73
+
80
74
  def aggs(params = {})
81
75
  add_body aggs: params
82
76
  end
@@ -130,20 +124,19 @@ module Stretchy
130
124
  end
131
125
 
132
126
  def range(params = {})
133
- require_context!
134
127
  add_params params, nil, :range_node
135
128
  end
136
129
 
137
130
  def geo_distance(params = {})
138
- add_params params, :filter, :geo_distance_node
131
+ add_params params, nil, :geo_distance_node
139
132
  end
140
133
 
141
134
  def boost(params = {}, options = {})
142
- return add_context(:boost) unless params.any?
135
+ return add_context(:boost) if Utils.is_empty? params
143
136
 
144
137
  subcontext = context.merge(boost: true)
145
138
  if params.is_a? self.class
146
- boost_json = options.merge(filter: params.filter_node.json)
139
+ boost_json = options.merge(filter: params.json)
147
140
  add_nodes Node.new(boost_json, subcontext)
148
141
  else
149
142
  add_nodes Factory.raw_boost_node(params, subcontext)
@@ -184,21 +177,8 @@ module Stretchy
184
177
  results_obj.ids.count
185
178
  end
186
179
 
187
- def method_missing(method, *args, &block)
188
- if collector.respond_to?(method)
189
- collector.send(method, *args, &block)
190
- else
191
- super
192
- end
193
- end
194
-
195
180
  private
196
181
 
197
- def require_context!
198
- return true if context?(:query) || context?(:filter)
199
- raise 'You must specify either query or filter context'
200
- end
201
-
202
182
  def args_to_context(*args)
203
183
  args.reduce({}) do |ctx, item|
204
184
  next ctx if item.nil?
@@ -23,9 +23,7 @@ module Stretchy
23
23
  end
24
24
 
25
25
  def extract_boost_params!(params)
26
- boost_params = Utils.extract_options!(params, BOOST_OPTIONS)
27
- boost_params = {weight: DEFAULT_WEIGHT} unless boost_params.any?
28
- boost_params
26
+ Utils.extract_options!(params, BOOST_OPTIONS)
29
27
  end
30
28
 
31
29
  def extract_function_score_options!(params)
@@ -53,19 +51,17 @@ module Stretchy
53
51
  context[:fn_score] = extract_function_score_options!(params)
54
52
  context[:boost] = true
55
53
  context[:filter] = true
56
- json = context[:query] ? {query: params} : params
57
- Node.new(boost_params.merge(filter: json), context)
54
+ boost_params.merge!(filter: params) unless Utils.is_empty? params
55
+ Node.new(boost_params, context)
58
56
  end
59
57
 
60
58
  def context_nodes(params, context = default_context)
61
- subparams = dotify_params(params, context)
62
-
63
59
  if context[:boost]
64
- params_to_boost(subparams, context)
65
- elsif context[:query]
66
- params_to_queries(subparams, context)
60
+ params_to_boost(params, context)
61
+ elsif context[:filter] && !context[:query]
62
+ params_to_filters(dotify_params(params, context), context)
67
63
  else
68
- params_to_filters(subparams, context)
64
+ params_to_queries(dotify_params(params, context), context)
69
65
  end
70
66
  end
71
67
 
@@ -76,14 +72,12 @@ module Stretchy
76
72
  nodes = context_nodes(params, subcontext)
77
73
  collector = AndCollector.new(nodes, subcontext)
78
74
 
79
- if context[:query]
80
- Node.new(boost_params.merge(filter: {query: collector.json}), context)
81
- else
82
- Node.new(
83
- boost_params.merge(filter: collector.filter_node.json),
84
- context
85
- )
75
+ boost_params.merge!(filter: collector.json) if collector.any?
76
+ if boost_params.count == 1 && boost_params.key?(:filter)
77
+ boost_params[:weight] = DEFAULT_WEIGHT
86
78
  end
79
+
80
+ Node.new(boost_params, context)
87
81
  end
88
82
 
89
83
  def params_to_queries(params, context = default_context)
@@ -100,7 +94,11 @@ module Stretchy
100
94
  when Hash
101
95
  nested(val, field, context)
102
96
  else
103
- Node.new({match: {field => val}}, context)
97
+ if field == '_all'
98
+ Node.new({multi_match: {:query => val}}, context)
99
+ else
100
+ Node.new({match: {field => val}}, context)
101
+ end
104
102
  end
105
103
  end
106
104
  end
@@ -111,7 +109,8 @@ module Stretchy
111
109
  when Range
112
110
  Node.new({range: {field => {gte: val.min, lte: val.max}}}, context)
113
111
  when nil
114
- Node.new({missing: {field: field}}, context)
112
+ nil_ctx = context.merge(must_not: true)
113
+ Node.new({exists: {field: field}}, nil_ctx)
115
114
  when Hash
116
115
  nested(val, field, context)
117
116
  else
@@ -121,19 +120,16 @@ module Stretchy
121
120
  end
122
121
 
123
122
  def nested(params, path, context = default_context)
124
- type, json = if context[:query]
125
- nodes = params_to_queries(params, context)
126
- json = AndCollector.new(nodes, context).json
127
- [:query, json]
123
+ nodes = if context[:filter] && !context[:query]
124
+ params_to_filters(params, context)
128
125
  else
129
- nodes = params_to_filters(params, context)
130
- json = AndCollector.new(nodes, context).filter_json
131
- [:filter, json]
126
+ params_to_queries(params, context)
132
127
  end
128
+ json = AndCollector.new(nodes, context).json
133
129
 
134
130
  Node.new({nested: {
135
131
  path: path,
136
- type => json
132
+ query: json
137
133
  }}, context)
138
134
  end
139
135
 
@@ -141,18 +137,16 @@ module Stretchy
141
137
  def fulltext_nodes_from_string(params, context = default_context)
142
138
  subcontext = context.merge(query: true)
143
139
  nodes = [raw_node({
144
- match: {
145
- _all: {
140
+ multi_match: {
146
141
  query: params,
147
142
  minimum_should_match: 1
148
143
  }
149
- }
150
144
  }, subcontext)]
151
145
 
152
146
  subcontext = subcontext.merge(should: true)
153
147
  nodes << Factory.raw_node({
154
148
  match_phrase: {
155
- _all: {
149
+ multi_match: {
156
150
  query: params,
157
151
  slop: DEFAULT_SLOP
158
152
  }
@@ -188,7 +182,7 @@ module Stretchy
188
182
 
189
183
  # https://www.elastic.co/guide/en/elasticsearch/reference/current/querydslfunctionscorequery.html#functionrandom
190
184
  def random_score_function_node(params, context = default_context)
191
- json = {random_score: {seed: params[:seed]}}
185
+ json = {random_score: {seed: params[:seed], field: :id}}
192
186
  json[:weight] = params[:weight] if params[:weight]
193
187
  Node.new(json, context)
194
188
  end
data/lib/stretchy/node.rb CHANGED
@@ -9,6 +9,10 @@ module Stretchy
9
9
  @context = context
10
10
  end
11
11
 
12
+ def empty?
13
+ !@json.any?
14
+ end
15
+
12
16
  def context?(*args)
13
17
  args.all? {|c| !!context[c] }
14
18
  end
@@ -1,3 +1,4 @@
1
+ require 'json'
1
2
  module Stretchy
2
3
  class Results
3
4
 
@@ -12,7 +13,10 @@ module Stretchy
12
13
  def self.fake
13
14
  self.new(
14
15
  {size: API::DEFAULT_PER_PAGE, fake: true},
15
- {'hits' => {'total' => 0, 'hits' => [], 'aggregations' => {}}}
16
+ {'hits' => {'total' => {
17
+ "value" => 3,
18
+ "relation" => "eq"
19
+ }, 'hits' => [], 'aggregations' => {}}}
16
20
  )
17
21
  end
18
22
 
@@ -43,7 +47,7 @@ module Stretchy
43
47
  end
44
48
 
45
49
  def total
46
- response['hits']['total']
50
+ response['hits']['total']['value']
47
51
  end
48
52
  alias :total_count :total
49
53
  alias :count :total
@@ -5,7 +5,9 @@ module Stretchy
5
5
  # detects empty string, empty array, empty hash, nil
6
6
  def is_empty?(arg = nil)
7
7
  return true if arg.nil?
8
- if arg.respond_to?(:any?)
8
+ if arg.respond_to?(:collector)
9
+ !arg.collector.any?
10
+ elsif arg.respond_to?(:any?)
9
11
  !arg.any? {|a| !is_empty?(a) }
10
12
  elsif arg.respond_to?(:empty?)
11
13
  arg.empty?
@@ -1,3 +1,3 @@
1
1
  module Stretchy
2
- VERSION = "0.5.3"
2
+ VERSION = "0.8.0"
3
3
  end
data/lib/stretchy.rb CHANGED
@@ -58,7 +58,7 @@ module Stretchy
58
58
  end
59
59
 
60
60
  def index_document(params = {})
61
- Utils.require_params!(:index_document, params, :index, :type, :body)
61
+ Utils.require_params!(:index_document, params, :index, :body)
62
62
 
63
63
  raise IndexDoesNotExistError.new(
64
64
  "index #{params[:index]} does not exist"
data/solano.yml CHANGED
@@ -1,9 +1,9 @@
1
1
  ---
2
- ruby_version: ruby-2.2.2
3
- bundler_version: 1.9.4
2
+ ruby_version: ruby-2.4.2
3
+ bundler_version: 1.14.6
4
4
  test_pattern:
5
5
  - spec/**/*_spec.rb
6
6
  elasticsearch:
7
- version: '1.6'
7
+ version: 5.0.1
8
8
  java:
9
- java_version: java-7-openjdk
9
+ java_version: java-8-openjdk
data/stretchy.gemspec CHANGED
@@ -19,14 +19,13 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "elasticsearch", "~> 1.0"
22
+ spec.add_dependency "elasticsearch", "~> 7.0"
23
23
  spec.add_dependency "excon", "~> 0.45"
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.8"
26
- spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rake", "~> 10.4"
27
26
  spec.add_development_dependency "rspec", "~> 3.2"
28
27
  spec.add_development_dependency "fuubar", "~> 2.0"
29
28
  spec.add_development_dependency "pry", "~> 0.10"
30
29
  spec.add_development_dependency "awesome_print", "~> 1.6"
31
- spec.add_development_dependency "yard", "~> 0.8"
30
+ spec.add_development_dependency "yard", "~> 0.9"
32
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stretchy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - agius
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-30 00:00:00.000000000 Z
11
+ date: 2021-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: elasticsearch
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '7.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '7.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: excon
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,34 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.45'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.8'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.8'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rake
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '10.0'
47
+ version: '10.4'
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '10.0'
54
+ version: '10.4'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rspec
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +114,14 @@ dependencies:
128
114
  requirements:
129
115
  - - "~>"
130
116
  - !ruby/object:Gem::Version
131
- version: '0.8'
117
+ version: '0.9'
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
122
  - - "~>"
137
123
  - !ruby/object:Gem::Version
138
- version: '0.8'
124
+ version: '0.9'
139
125
  description: Build queries for Elasticsearch with a chainable interface like ActiveRecord's.
140
126
  email:
141
127
  - andrew@atevans.com
@@ -145,14 +131,18 @@ extra_rdoc_files: []
145
131
  files:
146
132
  - ".editorconfig"
147
133
  - ".gitignore"
134
+ - ".rubocop.yml"
148
135
  - ".ruby-version"
149
136
  - ".yardopts"
137
+ - CHANGELOG.md
150
138
  - CONTRIBUTING.md
139
+ - Dockerfile
151
140
  - Gemfile
152
141
  - README.md
153
142
  - Rakefile
154
143
  - bin/console
155
144
  - bin/setup
145
+ - docker-compose.yml
156
146
  - lib/stretchy.rb
157
147
  - lib/stretchy/and_collector.rb
158
148
  - lib/stretchy/api.rb
@@ -184,10 +174,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
174
  - !ruby/object:Gem::Version
185
175
  version: '0'
186
176
  requirements: []
187
- rubyforge_project:
188
- rubygems_version: 2.4.5
177
+ rubygems_version: 3.0.3
189
178
  signing_key:
190
179
  specification_version: 4
191
180
  summary: Query builder for Elasticsearch
192
181
  test_files: []
193
- has_rdoc: