stretchy 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5822801c4cec4719808f4679f787570f97524b29
4
- data.tar.gz: 4684f243aee61ab42f4cc0032163301674afe5df
3
+ metadata.gz: 6d19628e7bb3b4177002806dee9ae3cd41e67340
4
+ data.tar.gz: cdb6536ac2450f5f8f01a6efab5071c0bb88e9f8
5
5
  SHA512:
6
- metadata.gz: 5ab85cf648c091546af556e5a4d86efa91f92889fdc155496be089087f546b8b1b0da6cc72e3868fde31f4b9178b8371211bf96f5deda5f730b2f6fe4af4c2c3
7
- data.tar.gz: 21ccd5b5e9178dddd2c9a5fefe1ce056a56458a62b9d3f3a0777b225c6bb3756c2a8788909b5822f419343e8d9d03567fe06cdb39ac1ff7840351b8062c3232e
6
+ metadata.gz: 1fb125ae7d1763bd44c2fef081d3a1ab2d3ae4e5a9289341e32b98617bd26dd667a387333b38d97ae6942da519d980ac380b28b738c12c80345e174c19b6f1d4
7
+ data.tar.gz: 1aa29437d28d4dcd4e85840d161f068f09569b2b3f4c008886cdebc1dc005eb50fc9d4aca120c21611b777721bfe971fa3daa4b7da3a116d006a6d54fbcd9960
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ -m markdown lib/**/*.rb - README.md
data/README.md CHANGED
@@ -33,10 +33,27 @@ Or install it yourself as:
33
33
 
34
34
  Stretchy is still in early development, so it does not yet support the full feature set of the [Elasticsearch API](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html). It does support fairly basic queries in an ActiveRecord-ish style.
35
35
 
36
+ ### Configuration
37
+
38
+ ```ruby
39
+ Stretchy.configure do |c|
40
+ c.index_name = 'my_index' # REQUIRED
41
+ c.client = $my_client # ignore below, use a custom client
42
+ c.url = 'https://user:pw@my.elastic.url' # default is ENV['ELASTICSEARCH_URL']
43
+ c.adapter = :patron # default is :excon
44
+
45
+ c.logger = Logger.new(STDOUT) # passed to elasticsearch-api gem
46
+ # Stretchy will also log, with the params
47
+ # specified below
48
+ c.log_level = :debug # default is :silence
49
+ c.log_color = :green # default is :blue
50
+ end
51
+ ```
52
+
36
53
  ### Base
37
54
 
38
55
  ```ruby
39
- query = Stretchy::Query.new(index: 'app_production', type: 'model_name')
56
+ query = Stretchy.query(type: 'model_name')
40
57
  ```
41
58
 
42
59
  From here, you can chain the following query methods:
@@ -44,57 +61,43 @@ From here, you can chain the following query methods:
44
61
  ### Match
45
62
 
46
63
  ```ruby
47
- query = query.match('welcome to my web site')
48
- query = query.match('welcome to my web site', field: 'title', operator: 'or')
64
+ query = query.match('welcome to my web site').match(title: 'welcome to my web site')
49
65
  ```
50
66
 
51
- Performs a full-text search for the given string. `field` and `operator` are optional, and default to `_all` and `and` respectively.
52
-
53
- #### Variants
54
-
55
- * `not_match` - filters for documents not matching a full-text search
67
+ Performs a full-text search for the given string. If given a hash, it will use a match query on the specified fields, otherwise it will default to `'_all'`.
56
68
 
57
69
 
58
70
  ### Where
59
71
 
60
72
  ```ruby
61
73
  query = query.where(
62
- name: 'Exact Name',
74
+ name: 'alice',
63
75
  email: [
64
- 'exact@email.com',
65
- 'another.user.with.same.name@email.com'
66
- ]
76
+ 'alice@company.com',
77
+ 'beatrice.christine@other_company.com'
78
+ ],
79
+ commit_count: 27..33,
80
+ is_robot: nil
67
81
  )
68
82
  ```
69
83
 
70
- Allows passing a hash of matchable options in `field: [values]` format. If any one of the values matches, that field will be considered matched. All fields must match for a document to be returned. See the [Terms filter](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html) for more details.
71
-
72
- If you pass `field: nil`, Stretchy will construct the relevant `not { exists: field }` filter and apply it as expected.
84
+ Allows passing a hash of matchable options similar to ActiveRecord's `where` method. To be returned, the document must match each of the parameters. If you pass an array of parameters for a field, the document must match at least one of those parameters.
73
85
 
74
86
  #### Gotcha
75
87
 
76
- Matches _must_ be exact; the values you pass in here are not analyzed by Elasticsearch, while the values stored in the index are (unless you turned analysis off for that field).
77
-
78
- #### Variants
79
-
80
- * `not_where` - filters for documents *not* matching the criteria
81
- * `boost_where` - boosts the relevance score for matching documents
82
- * `boost_not_where` - boosts the relevance score for documents not matching the criteria
88
+ If you pass a string or symbol for a field, it will be converted to a [Match Query](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html) for the specified field. Since Elastic analyzes terms by default, string or symbol terms will be looked for by an analyzed query.
83
89
 
84
90
  ### Range
85
91
 
86
92
  ```ruby
87
- query = query.range(field: 'rating', min: 3, max: 5)
93
+ query = query.range(:rating, min: 3, max: 5)
94
+ .range(:released, min: Time.now - 60*60*24*100)
95
+ .range(:quantity, max: 100, exclusive: true)
88
96
  ```
89
97
 
90
- Only documents with the specified field, and within the specified range (inclusive) match. You can also pass in dates and times as ranges. Currently, you must pass both a min and a max value.
91
-
92
- #### Variants
98
+ Only documents with the specified field, and within the specified range match. You can also pass in dates and times as ranges. While you could pass a normal ruby `Range` object to `.where`, this allows you to specify only a minimum or only a maximum. Range filters are inclusive by default, but you can also pass `:exclusive`, `:exclusive_min`, or `:exclusive_max`.
93
99
 
94
- * `not_range` - filters for only documents where the field is *outside* the given range
95
- * `boost_range` - boosts the relevance score for matching documents
96
-
97
- ### Geo
100
+ ### Geo Distance
98
101
 
99
102
  ```ruby
100
103
  query = query.geo(field: 'coords', distance: '20mi', lat: 35.0117, lng: 135.7683)
@@ -106,34 +109,63 @@ Filters for documents where the specified `geo_point` field is within the given
106
109
 
107
110
  The field must be mapped as a `geo_point` field. See [Elasticsearch types](http://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html) for more info.
108
111
 
109
- #### Variants
112
+ ### Not
113
+
114
+ ```ruby
115
+ query = query.where.not(rating: 0)
116
+ .match.not('angry')
117
+ .where.not.geo(field: 'coords', distance: '20mi', lat: 35.0117, lng: 135.7683)
118
+ ```
110
119
 
111
- * `not_geo` - filters for documents outside the specified range
112
- * `boost_geo` - boosts the relevance score for documents based on how far from the given point they are
120
+ Called after `where` or `match` will let you apply inverted filters. Any documents that match those filters will be excluded.
113
121
 
114
- ### Limit and Offset
122
+ ### Should
115
123
 
116
124
  ```ruby
117
- query = query.limit(20).offset(1000)
125
+ query = query.should(name: 'Sarah', awesomeness: 1000).should.not(awesomeness: 0)
118
126
  ```
119
127
 
120
- Works the same way as ActiveRecord's limit and offset methods.
128
+ Should filters work similarly to `.where`. Documents that do not match are still returned, but they have a lower relevancy score and will appear after documents that do match in the results. See Elastic's documentation for [BoolQuery](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html) and [BoolFilter](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html) for more info.
121
129
 
122
- ### Boost Random
130
+ ### Boost
123
131
 
124
132
  ```ruby
125
- query = query.boost_random(user.id, 1.4)
133
+ query = query.boost.where(category: 3, weight: 100)
134
+ .boost.range(:awesomeness, min: 10, weight: 10)
135
+ .boost.match.not('sucks')
126
136
  ```
127
137
 
128
- Provides a random-but-deterministic boost to relevance scores. The first parameter is required, and represents the random seed. The second parameter is optional, and represents the weight for the random factor. See [Random Scoring](http://www.elastic.co/guide/en/elasticsearch/guide/master/random-scoring.html) for more details.
138
+ Boosts use a [Function Score Query](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html) with filters to allow you to affect the score for the document. Each condition will be applied as a filter with an optional weight.
129
139
 
130
- ### Explain
140
+
141
+ ### Near
142
+
143
+ ```ruby
144
+ query = query.boost.near(field: :published_at, origin: Time.now, scale: '5d')
145
+ .boost.near(field: :coords, lat: 35.0117, lng: 135.7683, scale: '10mi', decay: 0.33, weight: 1000)
146
+ ```
147
+
148
+ Boosts a document by how close a given field is to a given `:origin` . Accepts dates, times, numbers, and geographical points. Unlike `.where.range` or `.boost.geo`, `.boost.near` is not a binary operation. All documents get a score for that field, which decays the further it is away from the origin point.
149
+
150
+ The `:scale` param determines how quickly the value falls off. In the example above, if a document's `:coords` field is 10 miles away from the starting point, its score is about 1/3 that of a document at the origin point.
151
+
152
+ See the [Function Score Query](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html) section on Decay Functions for more info.
153
+
154
+ ### Random
131
155
 
132
156
  ```ruby
133
- query = query.explain.results
157
+ query = query.boost.random(user.id, 50)
134
158
  ```
135
159
 
136
- Provides Elasticsearch explanation results in `query.response` . See [the explain documentation](http://www.elastic.co/guide/en/elasticsearch/reference/1.x/search-explain.html) for more info.
160
+ Gives each document a randomized boost with a given seed and optional weight. This allows you to show slightly different result sets to different users, but show the same result set to that user every time.
161
+
162
+ ### Limit and Offset
163
+
164
+ ```ruby
165
+ query = query.limit(20).offset(1000)
166
+ ```
167
+
168
+ Works the same way as ActiveRecord's limit and offset methods - analogous to Elasticsearch's `from` and `size` parameters.
137
169
 
138
170
  ### Response
139
171
 
@@ -149,7 +181,7 @@ Executes the query, returns the raw JSON response from Elasticsearch and caches
149
181
  query.results
150
182
  ```
151
183
 
152
- Executes the query and provides the parsed json for each hit returned by Elasticsearch.
184
+ Executes the query and provides the parsed json for each hit returned by Elasticsearch, along with `_index`, `_type`, `_id`, and `_score` fields.
153
185
 
154
186
  ### Ids
155
187
 
@@ -157,9 +189,7 @@ Executes the query and provides the parsed json for each hit returned by Elastic
157
189
  query.ids
158
190
  ```
159
191
 
160
- Provides only the ids for each hit. If your document ids are numeric (as is the case for most ActiveRecord-integrated documents), they will be converted to integers.
161
-
162
- This is somewhat intelligent - if you have already called `results` the ids will be fetched from there, otherwise it will run the search and skip the data-fetch phase in Elasticsearch.
192
+ Provides only the ids for each hit. If your document ids are numeric (as is the case for many ActiveRecord integrations), they will be converted to integers.
163
193
 
164
194
  ### Total
165
195
 
@@ -1,5 +1,17 @@
1
1
  module Stretchy
2
2
  module Clauses
3
+ # A Clause is the basic unit of Stretchy's chainable query syntax.
4
+ # Think of it as a state machine, with transitions between states
5
+ # being handled by methods that return another Clause. When you
6
+ # call the `where` method, it stores the params passed as an
7
+ # internal representation, to be compiled down to the Elastic query
8
+ # syntax, and returns a WhereClause. The WhereClause reflects the
9
+ # current state of the query, and gives you access to methods like
10
+ # `range` and `geo` to add more specific filters. It inherits
11
+ # other methods from the Base class, allowing other transitions.
12
+ #
13
+ # Attributes are copied when a new Clause is instanciated, so
14
+ # the underlying storage is maintained throughout the chain.
3
15
  class Base
4
16
 
5
17
  extend Forwardable
@@ -14,6 +26,19 @@ module Stretchy
14
26
  :took, :shards, :total, :max_score] => :query_results
15
27
  delegate [:range, :geo] => :where
16
28
 
29
+ #
30
+ # Generates a chainable query. The only required option for the
31
+ # first initialization is `:type` , which specifies what type
32
+ # to query on your index.
33
+ #
34
+ # @overload initialize(base_or_opts, options)
35
+ # @param base [Base] another clause to copy attributes from
36
+ # @param options [Hash] options to set on the new state
37
+ #
38
+ # @overload initialize(base_or_opts)
39
+ # @option base_or_opts [String] :index The Elastic index to query
40
+ # @option base_or_opts [String] :type The Lucene type to query on
41
+ # @option base_or_opts [true, false] :inverse Whether we are in a `not` context
17
42
  def initialize(base_or_opts = nil, options = {})
18
43
  if base_or_opts && !base_or_opts.is_a?(Hash)
19
44
  base = base_or_opts
@@ -26,6 +51,7 @@ module Stretchy
26
51
  @inverse = options[:inverse] || base.inverse
27
52
  @limit = base.get_limit
28
53
  @offset = base.get_offset
54
+ @explain = base.get_explain
29
55
  else
30
56
  options = Hash(base_or_opts).merge(options)
31
57
  @index_name = options[:index] || Stretchy.index_name
@@ -40,38 +66,128 @@ module Stretchy
40
66
  end
41
67
  end
42
68
 
69
+ #
70
+ # Sets how many results to return, similar to
71
+ # ActiveRecord's limit method.
72
+ #
73
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html Elastic Docs - Request Body Search
74
+ #
75
+ # @param num [Integer] How many results to return
76
+ #
77
+ # @return [self]
43
78
  def limit(num)
44
79
  @limit = num
45
80
  self
46
81
  end
47
82
 
83
+ #
84
+ # Accessor for `@limit`
85
+ #
86
+ # @return [Integer] Value of `@limit`
48
87
  def get_limit
49
88
  @limit
50
89
  end
51
90
 
91
+ #
92
+ # Sets the offset to start returning results at.
93
+ # Corresponds to Elastic's "from" parameter
94
+ #
95
+ # @param num [Integer] Offset for query
96
+ #
97
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html Elastic Docs - Request Body Search
98
+ #
99
+ # @return [self]
52
100
  def offset(num)
53
101
  @offset = num
54
102
  self
55
103
  end
56
104
 
105
+ #
106
+ # Accessor for `@offset`
107
+ #
108
+ # @return [Integer] Offset for query
57
109
  def get_offset
58
110
  @offset
59
111
  end
60
112
 
113
+ #
114
+ # Tells the search to explain the scoring
115
+ # mechanism for each document.
116
+ #
117
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-explain.html Elastic Docs - Request Body Search (explain)
118
+ #
119
+ # @return [self] Allows continuing the query chain
120
+ def explain
121
+ @explain = true
122
+ self
123
+ end
124
+
125
+ def get_explain
126
+ !!@explain
127
+ end
128
+
129
+ #
130
+ # Used for fulltext searching. Works similarly
131
+ # to {#where} .
132
+ #
133
+ # @param options = {} [Hash] Options to be passed to
134
+ # the MatchClause
135
+ #
136
+ # @return [MatchClause] query state with fulltext matches
137
+ #
138
+ # @see MatchClause#initialize
139
+ #
140
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html Elastic Docs - Match Query
61
141
  def match(options = {})
62
142
  MatchClause.new(self, options)
63
143
  end
64
144
  alias :fulltext :match
65
145
 
146
+ #
147
+ # Used for filtering results. Works similarly to
148
+ # ActiveRecord's `where` method.
149
+ #
150
+ # @param options = {} [Hash] Options to be passed to
151
+ # the {WhereClause}
152
+ #
153
+ # @return [WhereClause] query state with filters
154
+ #
155
+ # @see WhereClause#initialize
66
156
  def where(options = {})
67
157
  WhereClause.new(self, options)
68
158
  end
69
159
  alias :filter :where
70
160
 
161
+ #
162
+ # Used for boosting the relevance score of
163
+ # search results. Options passed here correspond
164
+ # to `where`-style filters which boost a document
165
+ # if matched.
166
+ #
167
+ # @param options = {} [type] [description]
168
+ #
169
+ # @return [BoostClause] query in boost context
170
+ #
171
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html Elastic Docs - Function Score Query
71
172
  def boost(options = {})
72
173
  BoostClause.new(self, options)
73
174
  end
74
175
 
176
+ #
177
+ # Inverts the current context - the next method
178
+ # called, such as {#where} or {#match} will generate
179
+ # a filter specifying the document **does not**
180
+ # match the specified filter.
181
+ #
182
+ # @overload not(string)
183
+ # @param [String] A string that must not be anywhere
184
+ # in the document
185
+ #
186
+ # @overload not(opts_or_string)
187
+ # @param [Hash] Options to be passed to an inverted {WhereClause}
188
+ #
189
+ # @return [Base] A {WhereClause}, or a {MatchClause} if only a string
190
+ # is given (ie, doing a full-text search across the whole document)
75
191
  def not(opts_or_string = {}, opts = {})
76
192
  if opts_or_string.is_a?(Hash)
77
193
  WhereClause.new(self, opts_or_string.merge(inverse: true))
@@ -80,6 +196,24 @@ module Stretchy
80
196
  end
81
197
  end
82
198
 
199
+ #
200
+ # Adds filters in the `should` context. Operates just like
201
+ # {#where}, but these filters only serve to add to the
202
+ # relevance score of the returned documents, rather than
203
+ # being required to match.
204
+ #
205
+ # @overload should(opts_or_string)
206
+ # @param [String] A string to match via full-text search
207
+ # anywhere in the document.
208
+ #
209
+ # @overload should(opts_or_string)
210
+ # @param [Hash] Options to generate filters.
211
+ #
212
+ # @return [WhereClause] current query state with should clauses applied
213
+ #
214
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html Elastic Docs - Bool Query
215
+ #
216
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html Elastic Docs - Bool Filter
83
217
  def should(opts_or_string = {}, opts = {})
84
218
  if opts_or_string.is_a?(Hash)
85
219
  WhereClause.new(self, opts_or_string.merge(should: true))
@@ -88,10 +222,22 @@ module Stretchy
88
222
  end
89
223
  end
90
224
 
225
+ #
226
+ # Accessor for `@inverse`
227
+ #
228
+ # @return [true, false] If current context is inverse
91
229
  def inverse?
92
230
  !!@inverse
93
231
  end
94
232
 
233
+ #
234
+ # Compiles the internal representation of your filters,
235
+ # full-text queries, and boosts into the JSON to be
236
+ # passed to Elastic. If you want to know exactly what
237
+ # your query generated, you can call this method.
238
+ #
239
+ # @return [Hash] the query hash to be compiled to json
240
+ # and sent to Elastic
95
241
  def to_search
96
242
  return @to_search if @to_search
97
243
 
@@ -108,6 +254,12 @@ module Stretchy
108
254
  @to_search = @to_search.to_search
109
255
  end
110
256
 
257
+ #
258
+ # The Results object for this query, which handles
259
+ # sending the search request and providing convienent
260
+ # accessors for the response.
261
+ #
262
+ # @return [Results::Base] The results returned from Elastic
111
263
  def query_results
112
264
  @query_results ||= Stretchy::Results::Base.new(self)
113
265
  end
@@ -2,27 +2,124 @@ require 'stretchy/clauses/base'
2
2
 
3
3
  module Stretchy
4
4
  module Clauses
5
+ #
6
+ # A Boost clause encapsulates the boost query state. It
7
+ # basically says "the next where / range / match filter
8
+ # will be used to boost a document's score instead of
9
+ # selecting documents to return."
10
+ #
11
+ # Calling `.boost` by itself doesn't do anything, but
12
+ # the next method (`.near`, `.match`, etc) will specify
13
+ # a boost using the same syntax as other clauses. These
14
+ # methods take a `:weight` parameter specifying the weight
15
+ # to assign that boost.
16
+ #
17
+ # @author [atevans]
18
+ #
5
19
  class BoostClause < Base
6
20
 
7
21
  extend Forwardable
8
22
 
9
23
  delegate [:geo, :range] => :where
10
24
 
25
+ #
26
+ # Switch to the boost state, specifying that
27
+ # the next where / range / etc will be a boost
28
+ # instead of a regular filter / range / etc.
29
+ #
30
+ # @param base [Base] a clause to copy query state from
31
+ # @param options = {} [Hash] Options for the boost clause
32
+ # @option options [true, false] :inverse (nil) If this boost should also be in the inverse state
33
+ #
11
34
  def initialize(base, options = {})
12
35
  super(base)
13
36
  @inverse = options.delete(:inverse)
14
37
  end
15
38
 
39
+ #
40
+ # Changes query state to "match" in the context
41
+ # of boosting. Options here work the same way as
42
+ # {MatchClause#initialize}, but the combined query
43
+ # will be applied as a boost function.
44
+ #
45
+ # @param options = {} [Hash] options for full text matching
46
+ #
47
+ # @return [BoostMatchClause] query with boost match state
16
48
  def match(options = {})
17
49
  BoostMatchClause.new(self, options)
18
50
  end
19
51
  alias :fulltext :match
20
52
 
53
+ #
54
+ # Changes query state to "where" in the context
55
+ # of boosting. Works the same way as {WhereClause},
56
+ # but applies the generated filters as a boost
57
+ # function.
58
+ #
59
+ # @param options = {} [Hash] Filters to use in this boost.
60
+ #
61
+ # @return [BoostWhereClause] Query state with boost filters applied
62
+ #
21
63
  def where(options = {})
22
64
  BoostWhereClause.new(self, options)
23
65
  end
24
66
  alias :filter :where
25
67
 
68
+ #
69
+ # Adds a {Boosts::FieldDecayBoost}, which boosts
70
+ # a search result based on how close it is to a
71
+ # specified value. That value can be a date, time,
72
+ # number, or {Types::GeoPoint}
73
+ #
74
+ # Required:
75
+ #
76
+ # * `:field`
77
+ # * `:origin` or `:lat` & `:lng` combo
78
+ # * `:scale`
79
+ #
80
+ # @option options [Numeric] :field What field to check with this boost
81
+ # @option options [Date, Time, Numeric, Types::GeoPoint] :origin Boost score based on how close the field is to this value. Required unless {Types::GeoPoint} is present (:lat, :lng, etc)
82
+ # @option options [Numeric] :lat Latitude, for a geo point
83
+ # @option options [Numeric] :latitude Latitude, for a geo point
84
+ # @option options [Numeric] :lng Longitude, for a geo point
85
+ # @option options [Numeric] :lon Longitude, for a geo point
86
+ # @option options [Numeric] :longitude Longitude, for a geo point
87
+ # @option options [String] :scale When the field is this distance from origin, the boost will be multiplied by `:decay` . Default is 0.5, so when `:origin` is a geo point and `:scale` is '10mi', then this boost will be twice as much for a point at the origin as for one 10 miles away
88
+ # @option options [String] :offset Anything within this distance of the origin is boosted as if it were at the origin
89
+ # @option options [Symbol] :type (:gauss) What type of decay to use. One of `:linear`, `:exp`, or `:gauss`
90
+ # @option options [Numeric] :decay (0.5) How much the boost falls off when it is `:scale` distance from `:origin`
91
+ # @option options [Numeric] :weight (1.2) How strongly to weight this boost compared to others
92
+ #
93
+ # @example Boost near a geo point
94
+ # query.boost.near(
95
+ # field: :coords,
96
+ # distance: '27km',
97
+ # scale: '3mi',
98
+ # lat: 33.3,
99
+ # lng: 28.2
100
+ # )
101
+ #
102
+ # @example Boost near a date
103
+ # query.boost.near(
104
+ # field: :published_at,
105
+ # origin: Time.now,
106
+ # scale: '3d'
107
+ # )
108
+ #
109
+ # @example Boost near a number (with options)
110
+ # query.boost.near(
111
+ # field: :followers,
112
+ # origin: 100,
113
+ # scale: 50,
114
+ # offset: 2,
115
+ # type: :linear,
116
+ # decay: 0.75,
117
+ # weight: 10
118
+ # )
119
+ #
120
+ # @return [Base] Query with field decay filter added
121
+ #
122
+ # @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html Elastic Docs - Function Score Query
26
123
  def near(options = {})
27
124
  if options[:lat] || options[:latitude] ||
28
125
  options[:lng] || options[:longitude] || options[:lon]
@@ -34,31 +131,73 @@ module Stretchy
34
131
  end
35
132
  alias :geo :near
36
133
 
134
+ #
135
+ # Adds a {Boosts::RandomBoost} to the query, for slightly
136
+ # randomizing search results.
137
+ #
138
+ # @param seed [Numeric] The seed for the random value
139
+ # @param weight [Numeric] The weight for this random value
140
+ #
141
+ # @return [Base] Query with random boost applied
142
+ #
143
+ # @see http://www.elastic.co/guide/en/elasticsearch/guide/master/random-scoring.html Elastic Docs - Random Scoring
37
144
  def random(*args)
38
145
  @boost_builder.functions << Stretchy::Boosts::RandomBoost.new(*args)
39
146
  Base.new(self)
40
147
  end
41
148
 
149
+ #
150
+ # Defines a global boost for all documents in the query
151
+ #
152
+ # @param num [Numeric] Boost to apply to the whole query
153
+ #
154
+ # @return [self] Boost context with overall boost applied
42
155
  def all(num)
43
156
  @boost_builder.overall_boost = num
44
157
  self
45
158
  end
46
159
 
160
+ #
161
+ # The maximum boost that any document can have
162
+ #
163
+ # @param num [Numeric] Maximum score a document can have
164
+ #
165
+ # @return [self] Boost context with maximum score applied
47
166
  def max(num)
48
167
  @boost_builder.max_boost = num
49
168
  self
50
169
  end
51
170
 
171
+ #
172
+ # Set scoring mode for when a document matches multiple
173
+ # boost functions.
174
+ #
175
+ # @param mode [Symbol] Score mode. Can be one of `multiply sum avg first max min`
176
+ #
177
+ # @return [self] Boost context with score mode applied
52
178
  def score_mode(mode)
53
179
  @boost_builder.score_mode = mode
54
180
  self
55
181
  end
56
182
 
183
+ #
184
+ # Set boost mode for when a document matches multiple
185
+ # boost functions.
186
+ #
187
+ # @param mode [Symbol] Boost mode. Can be one of `multiply replace sum avg max min`
188
+ #
189
+ # @return [self] Boost context with boost mode applied
57
190
  def boost_mode(mode)
58
191
  @boost_builder.boost_mode = mode
59
192
  self
60
193
  end
61
194
 
195
+ #
196
+ # Switches to inverse context - boosts added with {#where}
197
+ # and #{match} will be applied to documents which *do not*
198
+ # match said filters.
199
+ #
200
+ # @return [BoostClause] Boost clause in inverse context
62
201
  def not(options = {})
63
202
  self.class.new(self, options.merge(inverse: !inverse?))
64
203
  end