stretchy 0.4.6 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +12 -0
- data/CONTRIBUTING.md +52 -0
- data/README.md +157 -40
- data/lib/stretchy/builders/filter_builder.rb +12 -7
- data/lib/stretchy/builders/query_builder.rb +1 -1
- data/lib/stretchy/builders/where_builder.rb +7 -3
- data/lib/stretchy/clauses/base.rb +63 -57
- data/lib/stretchy/clauses/boost_clause.rb +47 -49
- data/lib/stretchy/clauses/boost_match_clause.rb +52 -19
- data/lib/stretchy/clauses/boost_where_clause.rb +46 -28
- data/lib/stretchy/clauses/match_clause.rb +52 -42
- data/lib/stretchy/clauses/where_clause.rb +86 -70
- data/lib/stretchy/filters/params_filter.rb +27 -0
- data/lib/stretchy/filters.rb +1 -0
- data/lib/stretchy/queries/params_query.rb +21 -0
- data/lib/stretchy/queries.rb +1 -0
- data/lib/stretchy/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bb3f7a0f6f14bc73d684b45506a015cd918317c
|
4
|
+
data.tar.gz: b19ced09b03b858c73665729c33ccfc28273ef91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e398d741823c25233f394bc69aba19d1af5b550865a22d0fd58527af37c25ac4c2b60456c4d42babef7432b2c00a4895ba43d3f4755ebe449d15fcaefe33f5d7
|
7
|
+
data.tar.gz: e626fedbcd22e07642d14f28e7e97861101c615a893883fcfcd1a91b3abc1bcc742d8b976fb7f17a8470d556f012f50baf426642a6710555f8d2d69896086a3a
|
data/.editorconfig
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
# top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
# Global Project Settings
|
7
|
+
[*]
|
8
|
+
end_of_line = lf
|
9
|
+
insert_final_newline = true
|
10
|
+
trim_trailing_whitespace = true
|
11
|
+
indent_style = space
|
12
|
+
indent_size = 2
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
### Thank You!
|
2
|
+
|
3
|
+
Thanks for considering contributing to our project! We want to make Stretchy a great tool for integrating Elasticsearch with Ruby projects, and getting help from the community is always appreciated.
|
4
|
+
|
5
|
+
### Development
|
6
|
+
|
7
|
+
1. Fork it ( https://github.com/[my-github-username]/stretchy/fork )
|
8
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
9
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
10
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
11
|
+
5. Create a new Pull Request
|
12
|
+
|
13
|
+
### Bugfixes
|
14
|
+
|
15
|
+
Please add a spec to reproduce the bug, fix it, then update any documentation necessary.
|
16
|
+
|
17
|
+
### Documentation Changes
|
18
|
+
|
19
|
+
If you notice we've got something wrong in the docs, please feel welcome to fix it.
|
20
|
+
|
21
|
+
### New Features
|
22
|
+
|
23
|
+
Before adding new features to the query builder, please [open a new issue](https://github.com/hired/stretchy/issues) to discuss it. This helps ensure your new feature is in line with the project's goals, and that you don't invest a bunch of time in something we might reject.
|
24
|
+
|
25
|
+
### Documentation
|
26
|
+
|
27
|
+
Our documentation is far from perfect, but if you add new methods to the query chain (ie, anything in `lib/stretchy/clauses`) be sure to document that using the YARD syntax, and also add it to the README.
|
28
|
+
|
29
|
+
### Testing
|
30
|
+
|
31
|
+
We use rspec for testing, with the latest version of Elasticsearch and Ruby. Until we hit 1.0, no support for older versions of either is planned.
|
32
|
+
|
33
|
+
* Use unit tests to ensure basic classes (builders, clauses, etc) behave the way you expect.
|
34
|
+
* Test the output of `.to_search` to ensure the JSON being generated for Elasticsearch is what you expect.
|
35
|
+
* Write an integration test under `spec/integration` to ensure that using your search terms actually affects the search results.
|
36
|
+
|
37
|
+
We run all specs automatically through Solano CI, and specs must pass there before any merge.
|
38
|
+
|
39
|
+
### Versioning
|
40
|
+
|
41
|
+
The version is only bumped on master after a pull request is merged. We use [Semantic Versioning](http://semver.org/).
|
42
|
+
|
43
|
+
* Bug fixes will bump the patch version
|
44
|
+
* Small new additions will bump the minor version
|
45
|
+
* Behavior and backwards-incompatible changes will bump the major version
|
46
|
+
|
47
|
+
### Style
|
48
|
+
|
49
|
+
1. Use the included `.editorconfig` to manage [minor style things like indents and tabs-v-spaces](http://editorconfig.org/).
|
50
|
+
2. Generally follow the [Github Ruby style guide](https://github.com/styleguide/ruby).
|
51
|
+
3. [Rebase your branch](http://git-scm.com/docs/git-rebase) and squash commits into reasonable chunks with good commit messages. No `@wip` or `fix specs` commits, please. [Here are some guidelines](http://chris.beams.io/posts/git-commit/) for good commit messages.
|
52
|
+
4. Write specs however they make sense to read. Use `describe` and `it` if your test names make a sentence, or `context` and `specify` for more specific unit tests.
|
data/README.md
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
+
[![](https://ci.solanolabs.com:443/Hired/stretchy/badges/branches/master?badge_token=062c34bcb84d3502662722bf76a8b4ec9fa073d9)](https://ci.solanolabs.com:443/Hired/stretchy/suites/246591)
|
2
|
+
|
1
3
|
# Stretchy
|
2
4
|
|
3
|
-
Stretchy is a query builder for [Elasticsearch](https://www.elastic.co/products/elasticsearch). It helps you quickly construct the JSON to send to Elastic, which can get [rather complicated](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html).
|
5
|
+
Stretchy is a query builder for [Elasticsearch](https://www.elastic.co/products/elasticsearch). It helps you quickly construct the JSON to send to Elastic, which can get [rather complicated](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html).
|
4
6
|
|
5
|
-
Stretchy is modeled after ActiveRecord's interface and architecture - query objects are immutable and chainable, which makes quickly building the right query and caching the results easy.
|
7
|
+
Stretchy is modeled after ActiveRecord's interface and architecture - query objects are immutable and chainable, which makes quickly building the right query and caching the results easy. The goals are:
|
6
8
|
|
7
|
-
Stretchy
|
9
|
+
1. **Intuitive** - If you've used ActiveRecord, Mongoid, or other query builders, Stretchy shouldn't be a stretch
|
10
|
+
2. **Less Typing** - Queries built here should be _way_ fewer characters than building by hand
|
11
|
+
3. **Easy** - Implementing the right algorithms for your search needs should be simple
|
8
12
|
|
9
|
-
|
10
|
-
2. a way to manage Elasticsearch configuration
|
11
|
-
3. a general-purpose Elasticsearch API client
|
13
|
+
Stretchy is *not*:
|
12
14
|
|
13
|
-
|
15
|
+
1. an integration with ActiveModel to help you index your data - too application specific
|
16
|
+
2. a way to manage Elasticsearch configuration - see [waistband](https://github.com/taskrabbit/waistband)
|
17
|
+
3. a general-purpose Elasticsearch API client - see the [elasticsearch gem](http://www.rubydoc.info/gems/elasticsearch-api/)
|
14
18
|
|
15
19
|
## Installation
|
16
20
|
|
@@ -30,7 +34,9 @@ Or install it yourself as:
|
|
30
34
|
|
31
35
|
## Usage
|
32
36
|
|
33
|
-
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).
|
37
|
+
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). There may be bugs, though we try for solid spec coverage. We may introduce breaking changes in minor versions, though we try to stick with [semantic versioning](http://semver.org).
|
38
|
+
|
39
|
+
It does support fairly basic queries in an ActiveRecord-ish style.
|
34
40
|
|
35
41
|
### Documentation
|
36
42
|
|
@@ -49,7 +55,7 @@ Stretchy.configure do |c|
|
|
49
55
|
# Stretchy will also log, with the params
|
50
56
|
# specified below
|
51
57
|
c.log_level = :debug # default is :silence
|
52
|
-
c.log_color = :green # default is :blue
|
58
|
+
c.log_color = :green # default is :blue
|
53
59
|
end
|
54
60
|
```
|
55
61
|
|
@@ -59,9 +65,32 @@ end
|
|
59
65
|
query = Stretchy.query(type: 'model_name')
|
60
66
|
```
|
61
67
|
|
68
|
+
From here, you can chain the methods to build your desired query.
|
69
|
+
|
70
|
+
## Chainable Query Methods
|
71
|
+
|
62
72
|
From here, you can chain the following query methods:
|
63
73
|
|
64
|
-
|
74
|
+
* [fulltext](#fulltext) - generic fulltext search with proximity relevance
|
75
|
+
* [match](#match) - Elasticsearch match query
|
76
|
+
* [query](#query) - Add arbitrary json fragment to the query section
|
77
|
+
* [more_like](#more-like) - Get documents similar to a string or other documents
|
78
|
+
* [where](#where) - Filter based on fields in the document
|
79
|
+
* [terms](#terms) - Filter without analyzing strings or symbols
|
80
|
+
* [filter](#filter) - Add arbitrary json fragment to the filter section
|
81
|
+
* [range](#range) - Filter for a range of values
|
82
|
+
* [geo](#geo-distance) - Filter on geo_point fields within a specified distance
|
83
|
+
* [not](#not) - Get documents not matching passed conditions
|
84
|
+
* [should](#should) - Increase document score for matching documents
|
85
|
+
* [boost](#boost) - Increasing document score based on different factors
|
86
|
+
* [near](#near) - Boost score based on how close a number / date / geo point is to an origin
|
87
|
+
* [field](#field) - Boost based on the numeric value of the passed field
|
88
|
+
* [random](#random) - Add a deterministic random factor to the document score
|
89
|
+
* [explain](#explain) - Return score explanations along with documents
|
90
|
+
* [fields](#fields) - Only return the specified fields
|
91
|
+
* [page](#limit) - Limit, Offset, and Page to define which results to return
|
92
|
+
|
93
|
+
### <a id="fulltext"></a>Fulltext
|
65
94
|
|
66
95
|
```ruby
|
67
96
|
query = query.fulltext('Generic user-input phrase')
|
@@ -70,7 +99,7 @@ query = query.fulltext('Generic user-input phrase')
|
|
70
99
|
|
71
100
|
Performs a query for the given string, either anywhere in the document or in specific fields. At least one of the terms must match, and the closer a document is to having the exact phrase, the higher its' score. See the Elasticsearch guide's [article on proximity scoring](https://www.elastic.co/guide/en/elasticsearch/guide/current/proximity-relevance.html) for more info on how this works.
|
72
101
|
|
73
|
-
### Match
|
102
|
+
### <a id="match"></a>Match
|
74
103
|
|
75
104
|
```ruby
|
76
105
|
query = query.match('welcome to my web site')
|
@@ -80,7 +109,31 @@ query = query.match('welcome to my web site')
|
|
80
109
|
|
81
110
|
Performs a match query for the given string. If given a hash, it will use a match query on the specified fields, otherwise it will default to `'_all'`. By default, a match query searches for any of the analyzed terms in the document, and scores them using Lucene's [practical scoring formula](https://www.elastic.co/guide/en/elasticsearch/guide/current/practical-scoring-function.html), which combines TF/IDF, the vector space model, and a few other niceties.
|
82
111
|
|
83
|
-
###
|
112
|
+
### <a id="query"></a>Query
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
query = query.match.query(
|
116
|
+
multi_match: {
|
117
|
+
query: 'super smash bros',
|
118
|
+
fields: ['developer.games', 'developer.bio']
|
119
|
+
}
|
120
|
+
)
|
121
|
+
|
122
|
+
query = query.match.not.match.query(
|
123
|
+
multi_match: {
|
124
|
+
query: 'rez',
|
125
|
+
fields: ['developer.games', 'developer.bio']
|
126
|
+
}
|
127
|
+
)
|
128
|
+
```
|
129
|
+
|
130
|
+
Adds arbitrary JSON to the query section of the final query. If you want to use a query type not currently supported by Stretchy, you can call this method and pass in the requisite json fragment. You can also prefix this with `.not` and `.should` to add your json to those sections of the query instead.
|
131
|
+
|
132
|
+
#### Caution
|
133
|
+
|
134
|
+
Stretchy tries to merge together matches on the same fields to optimize the final query to be sent to Elastic, but will not try to optimize any json added via the `.query` method.
|
135
|
+
|
136
|
+
### <a id="more-like"></a>More Like
|
84
137
|
|
85
138
|
```ruby
|
86
139
|
query = query.more_like(ids: [1, 2, 3])
|
@@ -90,7 +143,7 @@ query = query.more_like(ids: [1, 2, 3])
|
|
90
143
|
|
91
144
|
Finds documents similar to a list of input documents. You must pass in one of the `:ids`, `:docs` or `:like_text` parameters, but everything else is optional. This method accepts any of the params available in the [Elasticsearch more_like_this query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html). It can also be chained with `.not` and `.should`.
|
92
145
|
|
93
|
-
### Where
|
146
|
+
### <a id="where"></a>Where
|
94
147
|
|
95
148
|
```ruby
|
96
149
|
query = query.where(
|
@@ -112,7 +165,7 @@ If you pass a string or symbol for a field, it will be converted to a [Match Que
|
|
112
165
|
|
113
166
|
To query for _exact_ matches against strings or symbols with underscores and punctuation intact, use the `.where.terms` clause.
|
114
167
|
|
115
|
-
### Terms
|
168
|
+
### <a id="terms"></a>Terms
|
116
169
|
|
117
170
|
```ruby
|
118
171
|
query = query.where.terms(
|
@@ -123,7 +176,29 @@ query = query.where.terms(
|
|
123
176
|
|
124
177
|
Sometimes you store values with punctuation, underscores, or other characters Elasticsearch would normally split into separate terms. If you want to query all comments that match a specific email address, you need to make sure that Elasticsearch doesn't analyze the query terms you send it before running the query. This clause allows you to do that.
|
125
178
|
|
126
|
-
###
|
179
|
+
### <a id="filter"></a>Filter
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
query = query.filter(
|
183
|
+
geo_polygon: {
|
184
|
+
'person.location' => {
|
185
|
+
points: [
|
186
|
+
{lat: 40, lon: -70},
|
187
|
+
{lat: 30, lon: -80},
|
188
|
+
{lat: 20, lon: -90}
|
189
|
+
]
|
190
|
+
}
|
191
|
+
}
|
192
|
+
)
|
193
|
+
```
|
194
|
+
|
195
|
+
Adds arbitrary JSON to the filter section of the final query. If you want to use a filter type not currently supported by Stretchy, you can call this method and pass in the requisite json fragment. You can also prefix this with `.not` and `.should` to add your json to those sections of the filters instead.
|
196
|
+
|
197
|
+
#### Caution
|
198
|
+
|
199
|
+
Stretchy tries to merge together filters on the same fields to optimize the final query to be sent to Elastic, but will not try to optimize any json added via the `.filter` method.
|
200
|
+
|
201
|
+
### <a id="range"></a>Range
|
127
202
|
|
128
203
|
```ruby
|
129
204
|
query = query.range(:rating, min: 3, max: 5)
|
@@ -133,10 +208,10 @@ query = query.range(:rating, min: 3, max: 5)
|
|
133
208
|
|
134
209
|
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`.
|
135
210
|
|
136
|
-
### Geo Distance
|
211
|
+
### <a id="geo-distance"></a>Geo Distance
|
137
212
|
|
138
213
|
```ruby
|
139
|
-
query = query.geo(
|
214
|
+
query = query.geo('coords', distance: '20mi', lat: 35.0117, lng: 135.7683)
|
140
215
|
```
|
141
216
|
|
142
217
|
Filters for documents where the specified `geo_point` field is within the given range.
|
@@ -145,7 +220,7 @@ Filters for documents where the specified `geo_point` field is within the given
|
|
145
220
|
|
146
221
|
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.
|
147
222
|
|
148
|
-
### Not
|
223
|
+
### <a id="not"></a>Not
|
149
224
|
|
150
225
|
```ruby
|
151
226
|
query = query.where.not(rating: 0)
|
@@ -155,7 +230,7 @@ query = query.where.not(rating: 0)
|
|
155
230
|
|
156
231
|
Called after `where` or `match` will let you apply inverted filters. Any documents that match those filters will be excluded.
|
157
232
|
|
158
|
-
### Should
|
233
|
+
### <a id="should"></a>Should
|
159
234
|
|
160
235
|
```ruby
|
161
236
|
query = query.should(name: 'Sarah', awesomeness: 1000).should.not(awesomeness: 0)
|
@@ -163,7 +238,7 @@ query = query.should(name: 'Sarah', awesomeness: 1000).should.not(awesomeness: 0
|
|
163
238
|
|
164
239
|
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.
|
165
240
|
|
166
|
-
### Boost
|
241
|
+
### <a id="boost"></a>Boost
|
167
242
|
|
168
243
|
```ruby
|
169
244
|
query = query.boost.where(category: 3, weight: 100)
|
@@ -174,20 +249,20 @@ query = query.boost.where(category: 3, weight: 100)
|
|
174
249
|
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.
|
175
250
|
|
176
251
|
|
177
|
-
### Near
|
252
|
+
### <a id="near"></a>Near
|
178
253
|
|
179
254
|
```ruby
|
180
255
|
query = query.boost.near(field: :published_at, origin: Time.now, scale: '5d')
|
181
256
|
.boost.near(field: :coords, lat: 35.0117, lng: 135.7683, scale: '10mi', decay: 0.33, weight: 1000)
|
182
257
|
```
|
183
258
|
|
184
|
-
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.
|
259
|
+
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.
|
185
260
|
|
186
261
|
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.
|
187
262
|
|
188
263
|
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.
|
189
264
|
|
190
|
-
### Field
|
265
|
+
### <a id="field"></a>Field
|
191
266
|
|
192
267
|
```ruby
|
193
268
|
query = query.boost.field(:popularity)
|
@@ -199,7 +274,7 @@ Boosts a document by a numeric value contained in the specified fields. You can
|
|
199
274
|
|
200
275
|
See the [Boosting By Popularity Guide](https://www.elastic.co/guide/en/elasticsearch/guide/current/boosting-by-popularity.html) and the [Field Value Factor documentation](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#_field_value_factor) for more info.
|
201
276
|
|
202
|
-
### Random
|
277
|
+
### <a id="random"></a>Random
|
203
278
|
|
204
279
|
```ruby
|
205
280
|
query = query.boost.random(user.id, 50)
|
@@ -207,23 +282,42 @@ query = query.boost.random(user.id, 50)
|
|
207
282
|
|
208
283
|
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.
|
209
284
|
|
210
|
-
###
|
285
|
+
### <a id="fields"></a>Fields
|
286
|
+
|
287
|
+
```ruby
|
288
|
+
query = query.fields(:name, :email, :id)
|
289
|
+
```
|
290
|
+
|
291
|
+
Instead of returning the entire document, only return the specified fields.
|
292
|
+
|
293
|
+
### <a id="limit"></a>Limit, Offset, and Page
|
211
294
|
|
212
295
|
```ruby
|
213
296
|
query = query.limit(20).offset(1000)
|
297
|
+
# or...
|
298
|
+
query = query.page(50, per_page: 20)
|
214
299
|
```
|
215
300
|
|
216
|
-
Works the same way as ActiveRecord's limit and offset methods - analogous to Elasticsearch's `from` and `size` parameters.
|
301
|
+
Works the same way as ActiveRecord's limit and offset methods - analogous to Elasticsearch's `from` and `size` parameters. The `.page` method allows you to set both at once, and is compatible with the [Kaminari gem](https://github.com/amatsuda/kaminari).
|
217
302
|
|
218
|
-
###
|
303
|
+
### <a id="explain"></a>Explain
|
219
304
|
|
220
305
|
```ruby
|
221
|
-
query.
|
306
|
+
query = query.explain.where()
|
222
307
|
```
|
223
308
|
|
224
|
-
|
309
|
+
Tells Elasticsearch to return an explanation of the score for each document. See [the explain parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-explain.html) for how this is used, and [the explain API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-explain.html) for what the explanations will look like.
|
310
|
+
|
311
|
+
## Result Methods
|
312
|
+
|
313
|
+
* [results](#results) - Result documents from this query
|
314
|
+
* [ids](#ids) - Ids of result documents instead of the full source
|
315
|
+
* [response](#response) - Raw response data from Elasticsearch
|
316
|
+
* [total](#total) - Total number of matching documents
|
317
|
+
* [explanations](#explanations) - Explanations for document scores
|
318
|
+
* [per_page](#per_page) - Included with `.limit_value` for Kaminari compatibility
|
225
319
|
|
226
|
-
### Results
|
320
|
+
### <a id="results"></a>Results
|
227
321
|
|
228
322
|
```ruby
|
229
323
|
query.results
|
@@ -231,7 +325,7 @@ query.results
|
|
231
325
|
|
232
326
|
Executes the query and provides the parsed json for each hit returned by Elasticsearch, along with `_index`, `_type`, `_id`, and `_score` fields.
|
233
327
|
|
234
|
-
### Ids
|
328
|
+
### <a id="ids"></a>Ids
|
235
329
|
|
236
330
|
```ruby
|
237
331
|
query.ids
|
@@ -239,7 +333,15 @@ query.ids
|
|
239
333
|
|
240
334
|
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.
|
241
335
|
|
242
|
-
###
|
336
|
+
### <a id="response"></a>Response
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
query.response
|
340
|
+
```
|
341
|
+
|
342
|
+
Executes the query, returns the raw JSON response from Elasticsearch and caches it. Use this to get at search API data not in the source documents.
|
343
|
+
|
344
|
+
### <a id="total"></a>Total
|
243
345
|
|
244
346
|
```ruby
|
245
347
|
query.total
|
@@ -247,16 +349,31 @@ query.total
|
|
247
349
|
|
248
350
|
Returns the total number of matches returned by the query - not just the current page. Makes plugging into [Kaminari](https://github.com/amatsuda/kaminari) a snap.
|
249
351
|
|
250
|
-
|
352
|
+
### <a id="explanations"></a>Explanations
|
251
353
|
|
252
|
-
|
354
|
+
```ruby
|
355
|
+
query.explanations
|
356
|
+
```
|
253
357
|
|
254
|
-
|
358
|
+
Collect the `'_explanation'` field for each result, so you can easily see how the document scores were computed.
|
359
|
+
|
360
|
+
### <a id="per-page"></a>Per Page, Limit Value, and Total Pages
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
results = query.query_results
|
364
|
+
results.per_page
|
365
|
+
results.limit_value
|
366
|
+
results.total_pages
|
367
|
+
```
|
368
|
+
|
369
|
+
Included in the Results object for Kaminari compatibility.
|
370
|
+
|
371
|
+
## Development
|
372
|
+
|
373
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `pry` for an interactive prompt that will allow you to experiment.
|
255
374
|
|
256
375
|
## Contributing
|
257
376
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
262
|
-
5. Create a new Pull Request
|
377
|
+
For bugs and feature requests, please [open a new issue](https://github.com/hired/stretchy/issues/new).
|
378
|
+
|
379
|
+
Please see [the CONTRIBUTING guide](https://github.com/hired/stretchy/blob/master/CONTRIBUTING.md) for guidelines on contributing to Stretchy.
|
@@ -2,17 +2,22 @@ module Stretchy
|
|
2
2
|
module Builders
|
3
3
|
class FilterBuilder
|
4
4
|
|
5
|
-
attr_reader :terms, :ranges, :geos, :exists, :inverse, :should
|
5
|
+
attr_reader :terms, :ranges, :geos, :exists, :filters, :inverse, :should
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@terms = Hash.new { [] }
|
9
9
|
@ranges = Hash.new { [] }
|
10
10
|
@geos = Hash.new { [] }
|
11
|
+
@filters = []
|
11
12
|
@exists = []
|
12
13
|
end
|
13
14
|
|
14
15
|
def any?
|
15
|
-
@terms
|
16
|
+
[@filters, @terms, @ranges, @geos, @exists].any?(&:any?)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_filter(filter)
|
20
|
+
@filters << filter
|
16
21
|
end
|
17
22
|
|
18
23
|
def add_terms(field, terms)
|
@@ -34,13 +39,13 @@ module Stretchy
|
|
34
39
|
end
|
35
40
|
|
36
41
|
def to_filters
|
37
|
-
|
38
|
-
|
42
|
+
_filters = @ranges.values + @geos.values
|
43
|
+
_filters += @terms.map do |field, values|
|
39
44
|
Filters::TermsFilter.new(field, values)
|
40
45
|
end
|
41
46
|
|
42
|
-
|
43
|
-
filters
|
47
|
+
_filters += @exists.map {|field| Filters::ExistsFilter.new(field) }
|
48
|
+
filters + _filters
|
44
49
|
end
|
45
50
|
|
46
51
|
private
|
@@ -50,4 +55,4 @@ module Stretchy
|
|
50
55
|
|
51
56
|
end
|
52
57
|
end
|
53
|
-
end
|
58
|
+
end
|
@@ -21,6 +21,10 @@ module Stretchy
|
|
21
21
|
(must.any? && must_not.any?) || should.any? || should_not.any?
|
22
22
|
end
|
23
23
|
|
24
|
+
def add_filter(filter, options = {})
|
25
|
+
builder_from_options(options).add_filter(filter)
|
26
|
+
end
|
27
|
+
|
24
28
|
def add_param(field, param, options = {})
|
25
29
|
case param
|
26
30
|
when nil
|
@@ -106,11 +110,11 @@ module Stretchy
|
|
106
110
|
elsif should_not.any?
|
107
111
|
filters = should_not.to_filters
|
108
112
|
if filters.count > 1
|
109
|
-
filters = Stretchy::Filters::OrFilter.new(filters)
|
113
|
+
filters = Stretchy::Filters::OrFilter.new(filters)
|
110
114
|
else
|
111
115
|
filters = filters.first
|
112
116
|
end
|
113
|
-
|
117
|
+
|
114
118
|
Stretchy::Filters::NotFilter.new(filters)
|
115
119
|
else
|
116
120
|
filters = should.to_filters
|
@@ -120,4 +124,4 @@ module Stretchy
|
|
120
124
|
end
|
121
125
|
end
|
122
126
|
end
|
123
|
-
end
|
127
|
+
end
|