search_flip 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/CHANGELOG.md +14 -0
- data/README.md +32 -30
- data/lib/search_flip/aggregatable.rb +2 -2
- data/lib/search_flip/aggregation.rb +1 -1
- data/lib/search_flip/connection.rb +19 -19
- data/lib/search_flip/criteria.rb +47 -29
- data/lib/search_flip/filterable.rb +5 -3
- data/lib/search_flip/http_client.rb +1 -1
- data/lib/search_flip/index.rb +30 -30
- data/lib/search_flip/post_filterable.rb +2 -2
- data/lib/search_flip/response.rb +13 -13
- data/lib/search_flip/version.rb +1 -1
- data/search_flip.gemspec +3 -3
- data/spec/search_flip/criteria_spec.rb +58 -1
- data/spec/search_flip/index_spec.rb +1 -1
- metadata +9 -11
- data/logo.svg +0 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3c58927cac30203caa9e781f7f27ad725938b7b4e441e47946de72bdca8810b
|
4
|
+
data.tar.gz: a38d31311c6968b614395251f713b651f833ccd02d6a08f22747a5489db283e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9437a0b1ed85637401e636ed9335d7a2a89592efed8a1a7a3071d6a0ebc49feafbeba05c33fda9b729fcc3b37d8f3b28d36394aef70176d378a392a4f2b06a50
|
7
|
+
data.tar.gz: 8b17ed3c7078a8e06f09123ee901094d01b2c158da3baef48ced35e8cee1f51b70251223906c8ad849e4c1b7bfc8fb4561cf70437f546f263f2d9171c443230e
|
data/.travis.yml
CHANGED
@@ -7,8 +7,9 @@ env:
|
|
7
7
|
- ES_IMAGE=elasticsearch:5.4
|
8
8
|
- ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:6.7.0
|
9
9
|
- ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.0.0
|
10
|
+
- ES_IMAGE=docker.elastic.co/elasticsearch/elasticsearch:7.3.0
|
10
11
|
rvm:
|
11
|
-
- ruby-
|
12
|
+
- ruby-2.6.2
|
12
13
|
before_install:
|
13
14
|
- docker-compose up -d
|
14
15
|
- sleep 10
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
|
2
2
|
# CHANGELOG
|
3
3
|
|
4
|
+
## v2.3.0
|
5
|
+
|
6
|
+
* [DEPRECATED] `SearchFlip::Criteria#should` is deprecated and will become
|
7
|
+
equivalent to `.must(bool: { should: ... })` in search_flip 3
|
8
|
+
* Added `SearchFlip::Criteria#explain`
|
9
|
+
|
10
|
+
## v2.2.0
|
11
|
+
|
12
|
+
* [DEPRECATED] `SearchFlip::Criteria#unscope` is deprecated and will be removed
|
13
|
+
in search_flip 3
|
14
|
+
* Added `SearchFlip::Criteria#track_total_hits`
|
15
|
+
|
16
|
+
## v2.1.0
|
17
|
+
|
4
18
|
## v2.0.0
|
5
19
|
|
6
20
|
* Added `SearchFlip::Connection`
|
data/README.md
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
|
2
2
|
# search_flip
|
3
3
|
|
4
|
-
**Full-Featured
|
4
|
+
**Full-Featured Elasticsearch Ruby Client with a Chainable DSL**
|
5
5
|
|
6
|
-
[![Build Status](https://secure.travis-ci.org/mrkamel/search_flip.
|
6
|
+
[![Build Status](https://secure.travis-ci.org/mrkamel/search_flip.svg?branch=master)](http://travis-ci.org/mrkamel/search_flip)
|
7
7
|
[![Gem Version](https://badge.fury.io/rb/search_flip.svg)](http://badge.fury.io/rb/search_flip)
|
8
8
|
|
9
9
|
Using SearchFlip it is dead-simple to create index classes that correspond to
|
10
|
-
[
|
10
|
+
[Elasticsearch](https://www.elastic.co/) indices and to manipulate, query and
|
11
11
|
aggregate these indices using a chainable, concise, yet powerful DSL. Finally,
|
12
|
-
SearchFlip supports
|
12
|
+
SearchFlip supports Elasticsearch 1.x, 2.x, 5.x, 6.x, 7.x. Check section
|
13
13
|
[Feature Support](#feature-support) for version dependent features.
|
14
14
|
|
15
15
|
```ruby
|
@@ -47,7 +47,7 @@ Comment.search(
|
|
47
47
|
Comment.search("hello world", where: { available: true }, order: { id: "desc" }, aggs: [:username])
|
48
48
|
|
49
49
|
# search_flip
|
50
|
-
CommentIndex.
|
50
|
+
CommentIndex.search("hello world").where(available: true).sort(id: "desc").aggregate(:username)
|
51
51
|
|
52
52
|
```
|
53
53
|
|
@@ -96,7 +96,7 @@ Available config options are:
|
|
96
96
|
* `bulk_limit` a global limit for bulk requests
|
97
97
|
* `bulk_max_mb` a global limit for the payload of bulk requests
|
98
98
|
* `auto_refresh` tells SearchFlip to automatically refresh an index after
|
99
|
-
import, index, delete, etc operations. This is e.g.
|
99
|
+
import, index, delete, etc operations. This is e.g. useful for testing, etc.
|
100
100
|
Defaults to false.
|
101
101
|
|
102
102
|
## Usage
|
@@ -109,7 +109,7 @@ class CommentIndex
|
|
109
109
|
end
|
110
110
|
```
|
111
111
|
|
112
|
-
Then tell the Index about the index name, the
|
112
|
+
Then tell the Index about the index name, the corresponding model and how to
|
113
113
|
serialize the model for indexing.
|
114
114
|
|
115
115
|
```ruby
|
@@ -211,7 +211,7 @@ CommentIndex.close_index
|
|
211
211
|
CommentIndex.open_index
|
212
212
|
```
|
213
213
|
|
214
|
-
|
214
|
+
Index records (automatically uses the [Bulk API]):
|
215
215
|
|
216
216
|
```ruby
|
217
217
|
CommentIndex.import(Comment.all)
|
@@ -220,7 +220,7 @@ CommentIndex.import([Comment.find(1), Comment.find(2)])
|
|
220
220
|
CommentIndex.import(Comment.where("created_at > ?", Time.now - 7.days))
|
221
221
|
```
|
222
222
|
|
223
|
-
|
223
|
+
Query records:
|
224
224
|
|
225
225
|
```ruby
|
226
226
|
CommentIndex.total_entries
|
@@ -238,7 +238,7 @@ CommentIndex.aggregate(:username).aggregations(:username)
|
|
238
238
|
```
|
239
239
|
|
240
240
|
Please note that you can check the request that will be send to Elasticsearch
|
241
|
-
by
|
241
|
+
by calling `#request` on the query:
|
242
242
|
|
243
243
|
```ruby
|
244
244
|
CommentIndex.search("hello world").sort(id: "desc").aggregate(:username).request
|
@@ -246,10 +246,10 @@ CommentIndex.search("hello world").sort(id: "desc").aggregate(:username).request
|
|
246
246
|
```
|
247
247
|
|
248
248
|
|
249
|
-
|
249
|
+
Delete records:
|
250
250
|
|
251
251
|
```ruby
|
252
|
-
# for
|
252
|
+
# for Elasticsearch >= 2.x and < 5.x, the delete-by-query plugin is required
|
253
253
|
# for the following query:
|
254
254
|
|
255
255
|
CommentIndex.match_all.delete
|
@@ -292,11 +292,10 @@ new_user.connection.update_aliases(actions: [
|
|
292
292
|
])
|
293
293
|
```
|
294
294
|
|
295
|
-
If the alias already exists, you
|
296
|
-
within `update_aliases`.
|
295
|
+
If the alias already exists, you have to remove it as well first within `update_aliases`.
|
297
296
|
|
298
|
-
Please note
|
299
|
-
temporary
|
297
|
+
Please note: `with_settings(index_name: '...')` returns an anonymous (i.e.
|
298
|
+
temporary) class which inherits from UserIndex and overwrites `index_name`.
|
300
299
|
|
301
300
|
## Chainable Methods
|
302
301
|
|
@@ -309,7 +308,7 @@ SearchFlip provides powerful methods to query/filter Elasticsearch:
|
|
309
308
|
|
310
309
|
* `where`
|
311
310
|
|
312
|
-
|
311
|
+
The `.where` method feels like ActiveRecord's `where` and adds a bool filter clause to the request:
|
313
312
|
|
314
313
|
```ruby
|
315
314
|
CommentIndex.where(reviewed: true)
|
@@ -319,7 +318,7 @@ CommentIndex.where(state: ["approved", "rejected"])
|
|
319
318
|
|
320
319
|
* `where_not`
|
321
320
|
|
322
|
-
|
321
|
+
The `.where_not` method is like `,where`, but excluding the matching documents:
|
323
322
|
|
324
323
|
```ruby
|
325
324
|
CommentIndex.where_not(id: [1, 2, 3])
|
@@ -327,7 +326,7 @@ CommentIndex.where_not(id: [1, 2, 3])
|
|
327
326
|
|
328
327
|
* `range`
|
329
328
|
|
330
|
-
|
329
|
+
Use `.range` to add a range filter query:
|
331
330
|
|
332
331
|
```ruby
|
333
332
|
CommentIndex.range(:created_at, gt: Date.today - 1.week, lt: Date.today)
|
@@ -335,7 +334,7 @@ CommentIndex.range(:created_at, gt: Date.today - 1.week, lt: Date.today)
|
|
335
334
|
|
336
335
|
* `filter`
|
337
336
|
|
338
|
-
Use
|
337
|
+
Use `.filter` to add raw filter queries:
|
339
338
|
|
340
339
|
```ruby
|
341
340
|
CommentIndex.filter(term: { state: "approved" })
|
@@ -343,7 +342,7 @@ CommentIndex.filter(term: { state: "approved" })
|
|
343
342
|
|
344
343
|
* `should`
|
345
344
|
|
346
|
-
Use
|
345
|
+
Use `.should` to add raw should queries:
|
347
346
|
|
348
347
|
```ruby
|
349
348
|
CommentIndex.should(term: { state: "approved" })
|
@@ -351,7 +350,7 @@ CommentIndex.should(term: { state: "approved" })
|
|
351
350
|
|
352
351
|
* `must`
|
353
352
|
|
354
|
-
Use
|
353
|
+
Use `.must` to add raw must queries:
|
355
354
|
|
356
355
|
```ruby
|
357
356
|
CommentIndex.must(term: { state: "approved" })
|
@@ -414,7 +413,7 @@ CommentIndex.match_all
|
|
414
413
|
|
415
414
|
All query/filter criteria methods (`#where`, `#where_not`, `#range`, etc.) are available
|
416
415
|
in post filter mode as well, ie. filters/queries applied after aggregations
|
417
|
-
are calculated. Checkout the
|
416
|
+
are calculated. Checkout the Elasticsearch docs for further info.
|
418
417
|
|
419
418
|
```ruby
|
420
419
|
query = CommentIndex.aggregate(:user_id)
|
@@ -436,7 +435,7 @@ query = OrderIndex.aggregate(:username, order: { revenue: "desc" }) do |aggregat
|
|
436
435
|
end
|
437
436
|
```
|
438
437
|
|
439
|
-
Generally, aggregation results returned by
|
438
|
+
Generally, aggregation results returned by Elasticsearch are returned as a
|
440
439
|
`SearchFlip::Result`, which basically is `Hashie::Mash`such that you can access
|
441
440
|
them via:
|
442
441
|
|
@@ -444,7 +443,7 @@ them via:
|
|
444
443
|
query.aggregations(:username)["mrkamel"].revenue.value
|
445
444
|
```
|
446
445
|
|
447
|
-
Still, if you want to get the raw aggregations returned by
|
446
|
+
Still, if you want to get the raw aggregations returned by Elasticsearch,
|
448
447
|
access them without supplying any aggregation name to `#aggregations`:
|
449
448
|
|
450
449
|
```ruby
|
@@ -615,7 +614,7 @@ end
|
|
615
614
|
* `failsafe`
|
616
615
|
|
617
616
|
Use `#failsafe` to prevent any exceptions from being raised for query string
|
618
|
-
syntax errors or
|
617
|
+
syntax errors or Elasticsearch being unavailable, etc.
|
619
618
|
|
620
619
|
```ruby
|
621
620
|
CommentIndex.search("invalid/request").execute
|
@@ -772,7 +771,7 @@ that work with whatever ORM you use.
|
|
772
771
|
|
773
772
|
## Date and Timestamps in JSON
|
774
773
|
|
775
|
-
|
774
|
+
Elasticsearch requires dates and timestamps to have one of the formats listed
|
776
775
|
here: [https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time).
|
777
776
|
|
778
777
|
However, `JSON.generate` in ruby by default outputs something like:
|
@@ -782,7 +781,7 @@ JSON.generate(time: Time.now.utc)
|
|
782
781
|
# => "{\"time\":\"2018-02-22 18:19:33 UTC\"}"
|
783
782
|
```
|
784
783
|
|
785
|
-
This format is not compatible with
|
784
|
+
This format is not compatible with Elasticsearch by default. If you're on
|
786
785
|
Rails, ActiveSupport adds its own `#to_json` methods to `Time`, `Date`, etc.
|
787
786
|
However, ActiveSupport checks whether they are used in combination with
|
788
787
|
`JSON.generate` or not and adapt:
|
@@ -848,7 +847,7 @@ model changes.
|
|
848
847
|
|
849
848
|
## Links
|
850
849
|
|
851
|
-
*
|
850
|
+
* Elasticsearch: [https://www.elastic.co/](https://www.elastic.co/)
|
852
851
|
* Reference Docs: [http://www.rubydoc.info/github/mrkamel/search_flip](http://www.rubydoc.info/github/mrkamel/search_flip)
|
853
852
|
* Travis: [http://travis-ci.org/mrkamel/search_flip](http://travis-ci.org/mrkamel/search_flip)
|
854
853
|
* will_paginate: [https://github.com/mislav/will_paginate](https://github.com/mislav/will_paginate)
|
@@ -866,7 +865,7 @@ model changes.
|
|
866
865
|
## Running the test suite
|
867
866
|
|
868
867
|
Running the tests is super easy. The test suite uses sqlite, such that you only
|
869
|
-
need to install
|
868
|
+
need to install Elasticsearch. You can install Elasticsearch on your own, or
|
870
869
|
you can e.g. use docker-compose:
|
871
870
|
|
872
871
|
```
|
@@ -876,3 +875,6 @@ $ rspec
|
|
876
875
|
```
|
877
876
|
|
878
877
|
That's it.
|
878
|
+
|
879
|
+
|
880
|
+
[Bulk API]: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
module SearchFlip
|
3
3
|
# The SearchFlip::Aggregatable mixin provides handy methods for using
|
4
|
-
# the
|
4
|
+
# the Elasticsearch aggregation framework, which can be chained with
|
5
5
|
# each other, all other criteria methods and even nested.
|
6
6
|
#
|
7
7
|
# @example
|
@@ -16,7 +16,7 @@ module SearchFlip
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# Adds an arbitrary aggregation to the request which can be chained as well
|
19
|
-
# as nested. Check out the examples and
|
19
|
+
# as nested. Check out the examples and Elasticsearch docs for further
|
20
20
|
# details.
|
21
21
|
#
|
22
22
|
# @example Basic usage with optons
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
module SearchFlip
|
3
3
|
# The SearchFlip::Aggregation class puts together everything
|
4
|
-
# required to use the
|
4
|
+
# required to use the Elasticsearch aggregation framework via mixins and
|
5
5
|
# adds a method to convert it to a hash format to be used in the request.
|
6
6
|
|
7
7
|
class Aggregation
|
@@ -20,12 +20,12 @@ module SearchFlip
|
|
20
20
|
@version_mutex = Mutex.new
|
21
21
|
end
|
22
22
|
|
23
|
-
# Queries and returns the
|
23
|
+
# Queries and returns the Elasticsearch version used.
|
24
24
|
#
|
25
25
|
# @example
|
26
26
|
# connection.version # => e.g. 2.4.1
|
27
27
|
#
|
28
|
-
# @return [String] The
|
28
|
+
# @return [String] The Elasticsearch version
|
29
29
|
|
30
30
|
def version
|
31
31
|
@version_mutex.synchronize do
|
@@ -33,7 +33,7 @@ module SearchFlip
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
# Queries and returns the
|
36
|
+
# Queries and returns the Elasticsearch cluster health.
|
37
37
|
#
|
38
38
|
# @example
|
39
39
|
# connection.cluster_health # => { "status" => "green", ... }
|
@@ -44,7 +44,7 @@ module SearchFlip
|
|
44
44
|
http_client.headers(accept: "application/json").get("#{base_url}/_cluster/health").parse
|
45
45
|
end
|
46
46
|
|
47
|
-
# Uses the
|
47
|
+
# Uses the Elasticsearch Multi Search API to execute multiple search requests
|
48
48
|
# within a single request. Raises SearchFlip::ResponseError in case any
|
49
49
|
# errors occur.
|
50
50
|
#
|
@@ -97,7 +97,7 @@ module SearchFlip
|
|
97
97
|
.parse
|
98
98
|
end
|
99
99
|
|
100
|
-
# Sends an analyze request to
|
100
|
+
# Sends an analyze request to Elasticsearch. Raises
|
101
101
|
# SearchFlip::ResponseError in case any errors occur.
|
102
102
|
#
|
103
103
|
# @example
|
@@ -131,7 +131,7 @@ module SearchFlip
|
|
131
131
|
Hashie::Mash.new(res)
|
132
132
|
end
|
133
133
|
|
134
|
-
# Returns whether or not the associated
|
134
|
+
# Returns whether or not the associated Elasticsearch alias already
|
135
135
|
# exists.
|
136
136
|
#
|
137
137
|
# @example
|
@@ -168,7 +168,7 @@ module SearchFlip
|
|
168
168
|
|
169
169
|
alias_method :cat_indices, :get_indices
|
170
170
|
|
171
|
-
# Creates the specified index within
|
171
|
+
# Creates the specified index within Elasticsearch and applies index
|
172
172
|
# settings, if specified. Raises SearchFlip::ResponseError in case any
|
173
173
|
# errors occur.
|
174
174
|
#
|
@@ -184,7 +184,7 @@ module SearchFlip
|
|
184
184
|
true
|
185
185
|
end
|
186
186
|
|
187
|
-
# Closes the specified index within
|
187
|
+
# Closes the specified index within Elasticsearch. Raises
|
188
188
|
# SearchFlip::ResponseError in case any errors occur
|
189
189
|
#
|
190
190
|
# @param index_name [String] The index name
|
@@ -197,7 +197,7 @@ module SearchFlip
|
|
197
197
|
true
|
198
198
|
end
|
199
199
|
|
200
|
-
# Opens the specified index within
|
200
|
+
# Opens the specified index within Elasticsearch. Raises
|
201
201
|
# SearchFlip::ResponseError in case any errors occur
|
202
202
|
#
|
203
203
|
# @param index_name [String] The index name
|
@@ -210,7 +210,7 @@ module SearchFlip
|
|
210
210
|
true
|
211
211
|
end
|
212
212
|
|
213
|
-
# Updates the index settings within
|
213
|
+
# Updates the index settings within Elasticsearch according to the index
|
214
214
|
# settings specified. Raises SearchFlip::ResponseError in case any
|
215
215
|
# errors occur.
|
216
216
|
#
|
@@ -225,7 +225,7 @@ module SearchFlip
|
|
225
225
|
true
|
226
226
|
end
|
227
227
|
|
228
|
-
# Fetches the index settings for the specified index from
|
228
|
+
# Fetches the index settings for the specified index from Elasticsearch.
|
229
229
|
# Sends a GET request to index_url/_settings. Raises
|
230
230
|
# SearchFlip::ResponseError in case any errors occur.
|
231
231
|
#
|
@@ -237,7 +237,7 @@ module SearchFlip
|
|
237
237
|
http_client.headers(accept: "application/json").get("#{index_url(index_name)}/_settings").parse
|
238
238
|
end
|
239
239
|
|
240
|
-
# Sends a refresh request to
|
240
|
+
# Sends a refresh request to Elasticsearch. Raises
|
241
241
|
# SearchFlip::ResponseError in case any errors occur.
|
242
242
|
#
|
243
243
|
# @param index_names [String, Array] The optional index names to refresh
|
@@ -250,7 +250,7 @@ module SearchFlip
|
|
250
250
|
end
|
251
251
|
|
252
252
|
# Updates the type mapping for the specified index and type within
|
253
|
-
#
|
253
|
+
# Elasticsearch according to the specified mapping. Raises
|
254
254
|
# SearchFlip::ResponseError in case any errors occur.
|
255
255
|
#
|
256
256
|
# @param index_name [String] The index name
|
@@ -270,7 +270,7 @@ module SearchFlip
|
|
270
270
|
end
|
271
271
|
|
272
272
|
# Retrieves the mapping for the specified index and type from
|
273
|
-
#
|
273
|
+
# Elasticsearch. Raises SearchFlip::ResponseError in case any errors occur.
|
274
274
|
#
|
275
275
|
# @param index_name [String] The index name
|
276
276
|
# @param type_name [String] The type name. Starting with Elasticsearch 7,
|
@@ -285,7 +285,7 @@ module SearchFlip
|
|
285
285
|
http_client.headers(accept: "application/json").get("#{url}/_mapping", params: params).parse
|
286
286
|
end
|
287
287
|
|
288
|
-
# Deletes the specified index from
|
288
|
+
# Deletes the specified index from Elasticsearch. Raises
|
289
289
|
# SearchFlip::ResponseError in case any errors occur.
|
290
290
|
#
|
291
291
|
# @param index_name [String] The index name
|
@@ -314,24 +314,24 @@ module SearchFlip
|
|
314
314
|
raise e
|
315
315
|
end
|
316
316
|
|
317
|
-
# Returns the full
|
317
|
+
# Returns the full Elasticsearch type URL, ie base URL, index name with
|
318
318
|
# prefix and type name.
|
319
319
|
#
|
320
320
|
# @param index_name [String] The index name
|
321
321
|
# @param type_name [String] The type name
|
322
322
|
#
|
323
|
-
# @return [String] The
|
323
|
+
# @return [String] The Elasticsearch type URL
|
324
324
|
|
325
325
|
def type_url(index_name, type_name)
|
326
326
|
"#{index_url(index_name)}/#{type_name}"
|
327
327
|
end
|
328
328
|
|
329
|
-
# Returns the
|
329
|
+
# Returns the Elasticsearch index URL for the specified index name, ie base
|
330
330
|
# URL and index name with prefix.
|
331
331
|
#
|
332
332
|
# @param index_name [String] The index name
|
333
333
|
#
|
334
|
-
# @return [String] The
|
334
|
+
# @return [String] The Elasticsearch index URL
|
335
335
|
|
336
336
|
def index_url(index_name)
|
337
337
|
"#{base_url}/#{index_name}"
|