chewy 0.9.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +214 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +41 -19
- data/.rubocop_todo.yml +2 -2
- data/.yardopts +5 -0
- data/Appraisals +58 -28
- data/CHANGELOG.md +153 -12
- data/Gemfile +20 -12
- data/LEGACY_DSL.md +497 -0
- data/LICENSE.txt +1 -1
- data/README.md +338 -528
- data/chewy.gemspec +11 -12
- data/gemfiles/rails.5.2.activerecord.gemfile +17 -0
- data/gemfiles/rails.5.2.mongoid.6.4.gemfile +17 -0
- data/gemfiles/rails.6.0.activerecord.gemfile +17 -0
- data/gemfiles/rails.6.1.activerecord.gemfile +19 -0
- data/gemfiles/ruby3.gemfile +10 -0
- data/gemfiles/sequel.4.45.gemfile +11 -0
- data/lib/chewy.rb +79 -44
- data/lib/chewy/backports/duplicable.rb +1 -1
- data/lib/chewy/config.rb +43 -17
- data/lib/chewy/errors.rb +2 -2
- data/lib/chewy/fields/base.rb +56 -31
- data/lib/chewy/fields/root.rb +44 -11
- data/lib/chewy/index.rb +237 -149
- data/lib/chewy/index/actions.rb +100 -35
- data/lib/chewy/index/aliases.rb +2 -1
- data/lib/chewy/index/settings.rb +11 -5
- data/lib/chewy/index/specification.rb +60 -0
- data/lib/chewy/journal.rb +40 -92
- data/lib/chewy/minitest/helpers.rb +6 -6
- data/lib/chewy/minitest/search_index_receiver.rb +17 -17
- data/lib/chewy/query.rb +182 -122
- data/lib/chewy/query/compose.rb +13 -13
- data/lib/chewy/query/criteria.rb +13 -13
- data/lib/chewy/query/filters.rb +21 -4
- data/lib/chewy/query/loading.rb +1 -2
- data/lib/chewy/query/nodes/and.rb +2 -2
- data/lib/chewy/query/nodes/bool.rb +1 -1
- data/lib/chewy/query/nodes/equal.rb +2 -2
- data/lib/chewy/query/nodes/exists.rb +1 -1
- data/lib/chewy/query/nodes/field.rb +1 -1
- data/lib/chewy/query/nodes/has_relation.rb +2 -2
- data/lib/chewy/query/nodes/match_all.rb +1 -1
- data/lib/chewy/query/nodes/missing.rb +1 -1
- data/lib/chewy/query/nodes/not.rb +2 -2
- data/lib/chewy/query/nodes/or.rb +2 -2
- data/lib/chewy/query/nodes/prefix.rb +1 -1
- data/lib/chewy/query/nodes/query.rb +2 -2
- data/lib/chewy/query/nodes/range.rb +4 -4
- data/lib/chewy/query/nodes/regexp.rb +4 -4
- data/lib/chewy/query/nodes/script.rb +3 -3
- data/lib/chewy/query/pagination.rb +10 -1
- data/lib/chewy/railtie.rb +4 -3
- data/lib/chewy/rake_helper.rb +265 -48
- data/lib/chewy/rspec/update_index.rb +33 -27
- data/lib/chewy/search.rb +79 -26
- data/lib/chewy/search/loader.rb +83 -0
- data/lib/chewy/{query → search}/pagination/kaminari.rb +13 -5
- data/lib/chewy/search/pagination/will_paginate.rb +43 -0
- data/lib/chewy/search/parameters.rb +168 -0
- data/lib/chewy/search/parameters/aggs.rb +16 -0
- data/lib/chewy/search/parameters/allow_partial_search_results.rb +27 -0
- data/lib/chewy/search/parameters/concerns/bool_storage.rb +24 -0
- data/lib/chewy/search/parameters/concerns/hash_storage.rb +23 -0
- data/lib/chewy/search/parameters/concerns/integer_storage.rb +14 -0
- data/lib/chewy/search/parameters/concerns/query_storage.rb +238 -0
- data/lib/chewy/search/parameters/concerns/string_array_storage.rb +23 -0
- data/lib/chewy/search/parameters/concerns/string_storage.rb +14 -0
- data/lib/chewy/search/parameters/docvalue_fields.rb +12 -0
- data/lib/chewy/search/parameters/explain.rb +16 -0
- data/lib/chewy/search/parameters/filter.rb +47 -0
- data/lib/chewy/search/parameters/highlight.rb +16 -0
- data/lib/chewy/search/parameters/indices.rb +123 -0
- data/lib/chewy/search/parameters/indices_boost.rb +52 -0
- data/lib/chewy/search/parameters/limit.rb +17 -0
- data/lib/chewy/search/parameters/load.rb +32 -0
- data/lib/chewy/search/parameters/min_score.rb +16 -0
- data/lib/chewy/search/parameters/none.rb +27 -0
- data/lib/chewy/search/parameters/offset.rb +17 -0
- data/lib/chewy/search/parameters/order.rb +64 -0
- data/lib/chewy/search/parameters/post_filter.rb +19 -0
- data/lib/chewy/search/parameters/preference.rb +16 -0
- data/lib/chewy/search/parameters/profile.rb +16 -0
- data/lib/chewy/search/parameters/query.rb +19 -0
- data/lib/chewy/search/parameters/request_cache.rb +27 -0
- data/lib/chewy/search/parameters/rescore.rb +29 -0
- data/lib/chewy/search/parameters/script_fields.rb +16 -0
- data/lib/chewy/search/parameters/search_after.rb +20 -0
- data/lib/chewy/search/parameters/search_type.rb +16 -0
- data/lib/chewy/search/parameters/source.rb +73 -0
- data/lib/chewy/search/parameters/storage.rb +95 -0
- data/lib/chewy/search/parameters/stored_fields.rb +63 -0
- data/lib/chewy/search/parameters/suggest.rb +16 -0
- data/lib/chewy/search/parameters/terminate_after.rb +16 -0
- data/lib/chewy/search/parameters/timeout.rb +16 -0
- data/lib/chewy/search/parameters/track_scores.rb +16 -0
- data/lib/chewy/search/parameters/types.rb +20 -0
- data/lib/chewy/search/parameters/version.rb +16 -0
- data/lib/chewy/search/query_proxy.rb +257 -0
- data/lib/chewy/search/request.rb +1046 -0
- data/lib/chewy/search/response.rb +119 -0
- data/lib/chewy/search/scoping.rb +50 -0
- data/lib/chewy/search/scrolling.rb +134 -0
- data/lib/chewy/stash.rb +79 -0
- data/lib/chewy/strategy.rb +10 -3
- data/lib/chewy/strategy/active_job.rb +2 -1
- data/lib/chewy/strategy/atomic.rb +2 -4
- data/lib/chewy/strategy/bypass.rb +1 -1
- data/lib/chewy/strategy/resque.rb +1 -0
- data/lib/chewy/strategy/shoryuken.rb +40 -0
- data/lib/chewy/strategy/sidekiq.rb +13 -3
- data/lib/chewy/type.rb +29 -7
- data/lib/chewy/type/actions.rb +26 -2
- data/lib/chewy/type/adapter/active_record.rb +44 -29
- data/lib/chewy/type/adapter/base.rb +27 -7
- data/lib/chewy/type/adapter/mongoid.rb +19 -10
- data/lib/chewy/type/adapter/object.rb +187 -26
- data/lib/chewy/type/adapter/orm.rb +59 -32
- data/lib/chewy/type/adapter/sequel.rb +33 -19
- data/lib/chewy/type/crutch.rb +1 -1
- data/lib/chewy/type/import.rb +146 -191
- data/lib/chewy/type/import/bulk_builder.rb +122 -0
- data/lib/chewy/type/import/bulk_request.rb +78 -0
- data/lib/chewy/type/import/journal_builder.rb +45 -0
- data/lib/chewy/type/import/routine.rb +138 -0
- data/lib/chewy/type/mapping.rb +51 -35
- data/lib/chewy/type/observe.rb +17 -13
- data/lib/chewy/type/syncer.rb +222 -0
- data/lib/chewy/type/witchcraft.rb +32 -16
- data/lib/chewy/type/wrapper.rb +30 -4
- data/lib/chewy/version.rb +1 -1
- data/lib/sequel/plugins/chewy_observe.rb +4 -19
- data/lib/tasks/chewy.rake +84 -26
- data/spec/chewy/config_spec.rb +98 -1
- data/spec/chewy/fields/base_spec.rb +170 -135
- data/spec/chewy/fields/root_spec.rb +124 -20
- data/spec/chewy/fields/time_fields_spec.rb +2 -3
- data/spec/chewy/index/actions_spec.rb +214 -52
- data/spec/chewy/index/aliases_spec.rb +2 -2
- data/spec/chewy/index/settings_spec.rb +67 -38
- data/spec/chewy/index/specification_spec.rb +169 -0
- data/spec/chewy/index_spec.rb +108 -64
- data/spec/chewy/journal_spec.rb +150 -55
- data/spec/chewy/minitest/helpers_spec.rb +4 -4
- data/spec/chewy/minitest/search_index_receiver_spec.rb +1 -1
- data/spec/chewy/query/criteria_spec.rb +179 -179
- data/spec/chewy/query/filters_spec.rb +16 -16
- data/spec/chewy/query/loading_spec.rb +22 -20
- data/spec/chewy/query/nodes/and_spec.rb +2 -2
- data/spec/chewy/query/nodes/bool_spec.rb +4 -4
- data/spec/chewy/query/nodes/equal_spec.rb +19 -19
- data/spec/chewy/query/nodes/exists_spec.rb +6 -6
- data/spec/chewy/query/nodes/has_child_spec.rb +19 -19
- data/spec/chewy/query/nodes/has_parent_spec.rb +19 -19
- data/spec/chewy/query/nodes/missing_spec.rb +5 -5
- data/spec/chewy/query/nodes/not_spec.rb +4 -2
- data/spec/chewy/query/nodes/or_spec.rb +2 -2
- data/spec/chewy/query/nodes/prefix_spec.rb +5 -5
- data/spec/chewy/query/nodes/query_spec.rb +2 -2
- data/spec/chewy/query/nodes/range_spec.rb +18 -18
- data/spec/chewy/query/nodes/raw_spec.rb +1 -1
- data/spec/chewy/query/nodes/regexp_spec.rb +14 -14
- data/spec/chewy/query/nodes/script_spec.rb +4 -4
- data/spec/chewy/query/pagination/kaminari_spec.rb +3 -55
- data/spec/chewy/query/pagination/will_paginate_spec.rb +5 -0
- data/spec/chewy/query/pagination_spec.rb +25 -21
- data/spec/chewy/query_spec.rb +503 -561
- data/spec/chewy/rake_helper_spec.rb +381 -0
- data/spec/chewy/repository_spec.rb +4 -4
- data/spec/chewy/rspec/update_index_spec.rb +89 -56
- data/spec/chewy/runtime_spec.rb +2 -2
- data/spec/chewy/search/loader_spec.rb +117 -0
- data/spec/chewy/search/pagination/kaminari_examples.rb +71 -0
- data/spec/chewy/search/pagination/kaminari_spec.rb +21 -0
- data/spec/chewy/search/pagination/will_paginate_examples.rb +63 -0
- data/spec/chewy/search/pagination/will_paginate_spec.rb +23 -0
- data/spec/chewy/search/parameters/aggs_spec.rb +5 -0
- data/spec/chewy/search/parameters/bool_storage_examples.rb +53 -0
- data/spec/chewy/search/parameters/docvalue_fields_spec.rb +5 -0
- data/spec/chewy/search/parameters/explain_spec.rb +5 -0
- data/spec/chewy/search/parameters/filter_spec.rb +5 -0
- data/spec/chewy/search/parameters/hash_storage_examples.rb +59 -0
- data/spec/chewy/search/parameters/highlight_spec.rb +5 -0
- data/spec/chewy/search/parameters/indices_spec.rb +191 -0
- data/spec/chewy/search/parameters/integer_storage_examples.rb +32 -0
- data/spec/chewy/search/parameters/limit_spec.rb +5 -0
- data/spec/chewy/search/parameters/load_spec.rb +60 -0
- data/spec/chewy/search/parameters/min_score_spec.rb +32 -0
- data/spec/chewy/search/parameters/none_spec.rb +5 -0
- data/spec/chewy/search/parameters/offset_spec.rb +5 -0
- data/spec/chewy/search/parameters/order_spec.rb +65 -0
- data/spec/chewy/search/parameters/post_filter_spec.rb +5 -0
- data/spec/chewy/search/parameters/preference_spec.rb +5 -0
- data/spec/chewy/search/parameters/profile_spec.rb +5 -0
- data/spec/chewy/search/parameters/query_spec.rb +5 -0
- data/spec/chewy/search/parameters/query_storage_examples.rb +388 -0
- data/spec/chewy/search/parameters/request_cache_spec.rb +67 -0
- data/spec/chewy/search/parameters/rescore_spec.rb +62 -0
- data/spec/chewy/search/parameters/script_fields_spec.rb +5 -0
- data/spec/chewy/search/parameters/search_after_spec.rb +32 -0
- data/spec/chewy/search/parameters/search_type_spec.rb +5 -0
- data/spec/chewy/search/parameters/source_spec.rb +156 -0
- data/spec/chewy/search/parameters/storage_spec.rb +60 -0
- data/spec/chewy/search/parameters/stored_fields_spec.rb +126 -0
- data/spec/chewy/search/parameters/string_array_storage_examples.rb +63 -0
- data/spec/chewy/search/parameters/string_storage_examples.rb +32 -0
- data/spec/chewy/search/parameters/suggest_spec.rb +5 -0
- data/spec/chewy/search/parameters/terminate_after_spec.rb +5 -0
- data/spec/chewy/search/parameters/timeout_spec.rb +5 -0
- data/spec/chewy/search/parameters/track_scores_spec.rb +5 -0
- data/spec/chewy/search/parameters/types_spec.rb +5 -0
- data/spec/chewy/search/parameters/version_spec.rb +5 -0
- data/spec/chewy/search/parameters_spec.rb +147 -0
- data/spec/chewy/search/query_proxy_spec.rb +68 -0
- data/spec/chewy/search/request_spec.rb +685 -0
- data/spec/chewy/search/response_spec.rb +198 -0
- data/spec/chewy/search/scrolling_spec.rb +169 -0
- data/spec/chewy/search_spec.rb +33 -16
- data/spec/chewy/stash_spec.rb +95 -0
- data/spec/chewy/strategy/active_job_spec.rb +21 -2
- data/spec/chewy/strategy/resque_spec.rb +6 -0
- data/spec/chewy/strategy/shoryuken_spec.rb +70 -0
- data/spec/chewy/strategy/sidekiq_spec.rb +13 -1
- data/spec/chewy/strategy_spec.rb +6 -6
- data/spec/chewy/type/actions_spec.rb +29 -10
- data/spec/chewy/type/adapter/active_record_spec.rb +203 -91
- data/spec/chewy/type/adapter/mongoid_spec.rb +112 -54
- data/spec/chewy/type/adapter/object_spec.rb +101 -28
- data/spec/chewy/type/adapter/sequel_spec.rb +149 -82
- data/spec/chewy/type/import/bulk_builder_spec.rb +279 -0
- data/spec/chewy/type/import/bulk_request_spec.rb +102 -0
- data/spec/chewy/type/import/journal_builder_spec.rb +95 -0
- data/spec/chewy/type/import/routine_spec.rb +110 -0
- data/spec/chewy/type/import_spec.rb +356 -271
- data/spec/chewy/type/mapping_spec.rb +96 -29
- data/spec/chewy/type/observe_spec.rb +9 -5
- data/spec/chewy/type/syncer_spec.rb +123 -0
- data/spec/chewy/type/witchcraft_spec.rb +61 -29
- data/spec/chewy/type/wrapper_spec.rb +63 -23
- data/spec/chewy/type_spec.rb +28 -7
- data/spec/chewy_spec.rb +75 -7
- data/spec/spec_helper.rb +17 -3
- data/spec/support/active_record.rb +5 -1
- data/spec/support/class_helpers.rb +0 -14
- data/spec/support/mongoid.rb +15 -3
- data/spec/support/sequel.rb +6 -1
- metadata +219 -58
- data/.travis.yml +0 -36
- data/gemfiles/rails.3.2.activerecord.gemfile +0 -16
- data/gemfiles/rails.3.2.activerecord.kaminari.gemfile +0 -15
- data/gemfiles/rails.3.2.activerecord.will_paginate.gemfile +0 -15
- data/gemfiles/rails.4.2.activerecord.gemfile +0 -17
- data/gemfiles/rails.4.2.activerecord.kaminari.gemfile +0 -16
- data/gemfiles/rails.4.2.activerecord.will_paginate.gemfile +0 -16
- data/gemfiles/rails.4.2.mongoid.4.0.gemfile +0 -16
- data/gemfiles/rails.4.2.mongoid.4.0.kaminari.gemfile +0 -15
- data/gemfiles/rails.4.2.mongoid.4.0.will_paginate.gemfile +0 -15
- data/gemfiles/rails.4.2.mongoid.5.1.gemfile +0 -16
- data/gemfiles/rails.4.2.mongoid.5.1.kaminari.gemfile +0 -15
- data/gemfiles/rails.4.2.mongoid.5.1.will_paginate.gemfile +0 -15
- data/gemfiles/rails.5.0.activerecord.gemfile +0 -17
- data/gemfiles/rails.5.0.activerecord.kaminari.gemfile +0 -16
- data/gemfiles/rails.5.0.activerecord.will_paginate.gemfile +0 -16
- data/gemfiles/sequel.4.38.gemfile +0 -14
- data/lib/chewy/journal/apply.rb +0 -31
- data/lib/chewy/journal/clean.rb +0 -24
- data/lib/chewy/journal/entry.rb +0 -83
- data/lib/chewy/journal/query.rb +0 -87
- data/lib/chewy/query/pagination/will_paginate.rb +0 -27
- data/lib/chewy/query/scoping.rb +0 -20
- data/spec/chewy/journal/apply_spec.rb +0 -120
- data/spec/chewy/journal/entry_spec.rb +0 -237
- data/spec/chewy/query/pagination/will_paginage_spec.rb +0 -59
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,53 +1,61 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/chewy.svg)](http://badge.fury.io/rb/chewy)
|
2
|
-
[![
|
2
|
+
[![CircleCI](https://circleci.com/gh/toptal/chewy/tree/master.svg?style=svg)](https://circleci.com/gh/toptal/chewy/tree/master)
|
3
3
|
[![Code Climate](https://codeclimate.com/github/toptal/chewy.svg)](https://codeclimate.com/github/toptal/chewy)
|
4
4
|
[![Inline docs](http://inch-ci.org/github/toptal/chewy.svg?branch=master)](http://inch-ci.org/github/toptal/chewy)
|
5
5
|
|
6
|
-
<p align="right">Sponsored by</p>
|
7
|
-
<p align="right"><a href="https://www.toptal.com/"><img src="https://www.toptal.com/assets/public/blocks/logo/big.png" alt="Toptal" width="105" height="34"></a></p>
|
8
|
-
|
9
6
|
# Chewy
|
10
7
|
|
11
|
-
Chewy is an ODM
|
8
|
+
Chewy is an ODM (Object Document Mapper), built on top of the [the official Elasticsearch client](https://github.com/elastic/elasticsearch-ruby).
|
12
9
|
|
13
10
|
## Table of Contents
|
14
11
|
|
15
|
-
* [Why Chewy?]
|
16
|
-
* [
|
17
|
-
|
18
|
-
* [
|
19
|
-
|
20
|
-
* [
|
21
|
-
* [
|
22
|
-
* [
|
23
|
-
* [
|
24
|
-
* [
|
25
|
-
* [
|
26
|
-
* [
|
27
|
-
* [
|
28
|
-
* [Index
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
* [
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
* [
|
37
|
-
* [
|
38
|
-
* [
|
39
|
-
* [
|
40
|
-
|
41
|
-
|
42
|
-
* [
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
* [
|
47
|
-
* [
|
12
|
+
* [Why Chewy?](#why-chewy)
|
13
|
+
* [Installation](#installation)
|
14
|
+
* [Usage](#usage)
|
15
|
+
* [Client settings](#client-settings)
|
16
|
+
* [AWS ElasticSearch configuration](#aws-elastic-search)
|
17
|
+
* [Index definition](#index-definition)
|
18
|
+
* [Type default import options](#type-default-import-options)
|
19
|
+
* [Multi (nested) and object field types](#multi-nested-and-object-field-types)
|
20
|
+
* [Parent and children types](#parent-and-children-types)
|
21
|
+
* [Geo Point fields](#geo-point-fields)
|
22
|
+
* [Crutches™ technology](#crutches-technology)
|
23
|
+
* [Witchcraft™ technology](#witchcraft-technology)
|
24
|
+
* [Raw Import](#raw-import)
|
25
|
+
* [Index creation during import](#index-creation-during-import)
|
26
|
+
* [Journaling](#journaling)
|
27
|
+
* [Types access](#types-access)
|
28
|
+
* [Index manipulation](#index-manipulation)
|
29
|
+
* [Index update strategies](#index-update-strategies)
|
30
|
+
* [Nesting](#nesting)
|
31
|
+
* [Non-block notation](#non-block-notation)
|
32
|
+
* [Designing your own strategies](#designing-your-own-strategies)
|
33
|
+
* [Rails application strategies integration](#rails-application-strategies-integration)
|
34
|
+
* [ActiveSupport::Notifications support](#activesupportnotifications-support)
|
35
|
+
* [NewRelic integration](#newrelic-integration)
|
36
|
+
* [Search requests](#search-requests)
|
37
|
+
* [Composing requests](#composing-requests)
|
38
|
+
* [Pagination](#pagination)
|
39
|
+
* [Named scopes](#named-scopes)
|
40
|
+
* [Scroll API](#scroll-api)
|
41
|
+
* [Loading objects](#loading-objects)
|
42
|
+
* [Legacy DSL incompatibilities](#legacy-dsl-incompatibilities)
|
43
|
+
* [Rake tasks](#rake-tasks)
|
44
|
+
* [chewy:reset](#chewyreset)
|
45
|
+
* [chewy:upgrade](#chewyupgrade)
|
46
|
+
* [chewy:update](#chewyupdate)
|
47
|
+
* [chewy:sync](#chewysync)
|
48
|
+
* [chewy:deploy](#chewydeploy)
|
49
|
+
* [Parallelizing rake tasks](#parallelizing-rake-tasks)
|
50
|
+
* [chewy:journal](#chewyjournal)
|
51
|
+
* [RSpec integration](#rspec-integration)
|
52
|
+
* [Minitest integration](#minitest-integration)
|
53
|
+
* [Contributing](#contributing)
|
48
54
|
|
49
55
|
## Why Chewy?
|
50
56
|
|
57
|
+
In this section we'll cover why you might want to use Chewy instead of the official `elasticsearch-ruby` client gem.
|
58
|
+
|
51
59
|
* Multi-model indices.
|
52
60
|
|
53
61
|
Index classes are independent from ORM/ODM models. Now, implementing e.g. cross-model autocomplete is much easier. You can just define the index and work with it in an object-oriented style. You can define several types for index - one per indexed model.
|
@@ -66,10 +74,9 @@ Chewy is an ODM and wrapper for [the official Elasticsearch client](https://gith
|
|
66
74
|
|
67
75
|
* Support for ActiveRecord, [Mongoid](https://github.com/mongoid/mongoid) and [Sequel](https://github.com/jeremyevans/sequel).
|
68
76
|
|
69
|
-
|
70
77
|
## Installation
|
71
78
|
|
72
|
-
Add this line to your application's Gemfile
|
79
|
+
Add this line to your application's `Gemfile`:
|
73
80
|
|
74
81
|
gem 'chewy'
|
75
82
|
|
@@ -81,13 +88,29 @@ Or install it yourself as:
|
|
81
88
|
|
82
89
|
$ gem install chewy
|
83
90
|
|
91
|
+
## Compatibility
|
92
|
+
|
93
|
+
### Ruby
|
94
|
+
|
95
|
+
Chewy is compatible with MRI 2.5-3.0¹.
|
96
|
+
|
97
|
+
> ¹ Ruby 3 is only supported with Rails 6.1
|
98
|
+
|
99
|
+
### Elasticsearch
|
100
|
+
|
101
|
+
Chewy 5 is compatible with Elasticsearch 5. Future versions of Chewy will support Elasticsearch 6 and Elasticsearch 7.
|
102
|
+
|
84
103
|
## Usage
|
85
104
|
|
86
105
|
### Client settings
|
87
106
|
|
88
|
-
There are two ways to configure the Chewy client:
|
107
|
+
There are two ways to configure the Chewy client:
|
89
108
|
|
90
|
-
|
109
|
+
* via the hash `Chewy.settings`
|
110
|
+
* via the configuration file `chewy.yml`
|
111
|
+
|
112
|
+
You can create `chewy.yml` manually or run `rails g chewy:install` to
|
113
|
+
generate it.
|
91
114
|
|
92
115
|
```ruby
|
93
116
|
# config/initializers/chewy.rb
|
@@ -119,6 +142,30 @@ Chewy.logger = Logger.new(STDOUT)
|
|
119
142
|
|
120
143
|
See [config.rb](lib/chewy/config.rb) for more details.
|
121
144
|
|
145
|
+
#### AWS Elasticsearch
|
146
|
+
|
147
|
+
If you would like to use AWS's Elasticsearch using an IAM user policy, you will need to sign your requests for the `es:*` action by injecting the appropriate headers passing a proc to `transport_options`.
|
148
|
+
You'll need an additional gem for Faraday middleware: add `gem 'faraday_middleware-aws-sigv4'` to your Gemfile.
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
require 'faraday_middleware/aws_sigv4'
|
152
|
+
|
153
|
+
Chewy.settings = {
|
154
|
+
host: 'http://my-es-instance-on-aws.us-east-1.es.amazonaws.com:80',
|
155
|
+
port: 80, # 443 for https host
|
156
|
+
transport_options: {
|
157
|
+
headers: { content_type: 'application/json' },
|
158
|
+
proc: -> (f) do
|
159
|
+
f.request :aws_sigv4,
|
160
|
+
service: 'es',
|
161
|
+
region: 'us-east-1',
|
162
|
+
access_key_id: ENV['AWS_ACCESS_KEY'],
|
163
|
+
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
164
|
+
end
|
165
|
+
}
|
166
|
+
}
|
167
|
+
```
|
168
|
+
|
122
169
|
### Index definition
|
123
170
|
|
124
171
|
1. Create `/app/chewy/users_index.rb`
|
@@ -178,7 +225,7 @@ See [config.rb](lib/chewy/config.rb) for more details.
|
|
178
225
|
|
179
226
|
define_type User.active.includes(:country, :badges, :projects) do
|
180
227
|
root date_detection: false do
|
181
|
-
template 'about_translations.*', type: '
|
228
|
+
template 'about_translations.*', type: 'text', analyzer: 'standard'
|
182
229
|
|
183
230
|
field :first_name, :last_name
|
184
231
|
field :email, analyzer: 'email'
|
@@ -198,7 +245,7 @@ See [config.rb](lib/chewy/config.rb) for more details.
|
|
198
245
|
```
|
199
246
|
|
200
247
|
[See index settings here](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html).
|
201
|
-
[See root object settings here](https://www.elastic.co/guide/en/elasticsearch/reference/current/
|
248
|
+
[See root object settings here](https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-field-mapping.html).
|
202
249
|
|
203
250
|
See [mapping.rb](lib/chewy/type/mapping.rb) for more details.
|
204
251
|
|
@@ -305,17 +352,29 @@ This will automatically set the type or root field to `object`. You may also spe
|
|
305
352
|
To define a multi field you have to specify any type except for `object` or `nested` in the root field:
|
306
353
|
|
307
354
|
```ruby
|
308
|
-
field :full_name, type: '
|
355
|
+
field :full_name, type: 'text', value: ->{ full_name.strip } do
|
309
356
|
field :ordered, analyzer: 'ordered'
|
310
357
|
field :untouched, index: 'not_analyzed'
|
311
358
|
end
|
312
359
|
```
|
313
360
|
|
314
|
-
The `value:` option for internal fields
|
361
|
+
The `value:` option for internal fields will no longer be effective.
|
362
|
+
|
363
|
+
### Parent and children types
|
364
|
+
|
365
|
+
To define [parent](https://www.elastic.co/guide/en/elasticsearch/guide/current/parent-child-mapping.html) type for a given index_type, you can include root options for the type where you can specify parent_type and parent_id
|
315
366
|
|
367
|
+
```ruby
|
368
|
+
define_type User.includes(:account) do
|
369
|
+
root parent: 'account', parent_id: ->{ account_id } do
|
370
|
+
field :created_at, type: 'date'
|
371
|
+
field :task_id, type: 'integer'
|
372
|
+
end
|
373
|
+
end
|
374
|
+
```
|
316
375
|
### Geo Point fields
|
317
376
|
|
318
|
-
You can use [Elasticsearch's geo mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/
|
377
|
+
You can use [Elasticsearch's geo mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html) with the `geo_point` field type, allowing you to query, filter and order by latitude and longitude. You can use the following hash format:
|
319
378
|
|
320
379
|
```ruby
|
321
380
|
field :coordinates, type: 'geo_point', value: ->{ {lat: latitude, lon: longitude} }
|
@@ -345,7 +404,7 @@ class ProductsIndex < Chewy::Index
|
|
345
404
|
end
|
346
405
|
```
|
347
406
|
|
348
|
-
Then the Chewy reindexing flow
|
407
|
+
Then the Chewy reindexing flow will look like the following pseudo-code (even in Mongoid):
|
349
408
|
|
350
409
|
```ruby
|
351
410
|
Product.includes(:categories).find_in_batches(1000) do |batch|
|
@@ -380,7 +439,7 @@ class ProductsIndex < Chewy::Index
|
|
380
439
|
end
|
381
440
|
```
|
382
441
|
|
383
|
-
An example flow
|
442
|
+
An example flow will look like this:
|
384
443
|
|
385
444
|
```ruby
|
386
445
|
Product.includes(:categories).find_in_batches(1000) do |batch|
|
@@ -481,12 +540,18 @@ end
|
|
481
540
|
|
482
541
|
Also, you can pass `:raw_import` option to the `import` method explicitly.
|
483
542
|
|
543
|
+
### Index creation during import
|
544
|
+
|
545
|
+
By default, when you perform import Chewy checks whether an index exists and creates it if it's absent.
|
546
|
+
You can turn off this feature to decrease Elasticsearch hits count.
|
547
|
+
To do so you need to set `skip_index_creation_on_import` parameter to `false` in your `config/chewy.yml`
|
548
|
+
|
484
549
|
|
485
550
|
### Journaling
|
486
551
|
|
487
552
|
You can record all actions that were made to the separate journal index in ElasticSearch.
|
488
|
-
When you create/update/destroy your
|
489
|
-
If you make something with a batch of
|
553
|
+
When you create/update/destroy your documents, it will be saved in this special index.
|
554
|
+
If you make something with a batch of documents (e.g. during index reset) it will be saved as a one record, including primary keys of each document that was affected.
|
490
555
|
Common journal record looks like this:
|
491
556
|
|
492
557
|
```json
|
@@ -506,7 +571,7 @@ Also, you can specify journal index name. For example:
|
|
506
571
|
```yaml
|
507
572
|
# config/chewy.yml
|
508
573
|
production:
|
509
|
-
journal: true
|
574
|
+
journal: true
|
510
575
|
journal_name: my_super_journal
|
511
576
|
```
|
512
577
|
|
@@ -526,12 +591,9 @@ class CityIndex
|
|
526
591
|
end
|
527
592
|
```
|
528
593
|
|
529
|
-
You may be wondering why do you need it? The answer is simple:
|
530
|
-
Imagine that:
|
531
|
-
You reset your index in Zero Downtime manner (to separate index), and meantime somebody keeps updating the data frequently (to old index). So all these actions will be written to the journal index and you'll be able to apply them after index reset with `Chewy::Journal::Apply.since(1.hour.ago.to_i)`.
|
594
|
+
You may be wondering why do you need it? The answer is simple: not to lose the data.
|
532
595
|
|
533
|
-
|
534
|
-
You can change it only if you pass `journal: true` parameter explicitly to `#import`.
|
596
|
+
Imagine that you reset your index in a zero-downtime manner (to separate index), and at the meantime somebody keeps updating the data frequently (to old index). So all these actions will be written to the journal index and you'll be able to apply them after index reset using the `Chewy::Journal` interface.
|
535
597
|
|
536
598
|
### Types access
|
537
599
|
|
@@ -563,6 +625,7 @@ UsersIndex::User.import # import with 0 arguments process all the data specified
|
|
563
625
|
UsersIndex::User.import User.where('rating > 100') # or import specified users scope
|
564
626
|
UsersIndex::User.import User.where('rating > 100').to_a # or import specified users array
|
565
627
|
UsersIndex::User.import [1, 2, 42] # pass even ids for import, it will be handled in the most effective way
|
628
|
+
UsersIndex::User.import User.where('rating > 100'), update_fields: [:email] # if update fields are specified - it will update their values only with the `update` bulk action.
|
566
629
|
|
567
630
|
UsersIndex.import # import every defined type
|
568
631
|
UsersIndex.import user: User.where('rating > 100') # import only active users to `user` type.
|
@@ -632,6 +695,11 @@ Chewy.strategy(:sidekiq) do
|
|
632
695
|
end
|
633
696
|
```
|
634
697
|
|
698
|
+
The default queue name is `chewy`, you can customize it in settings: `sidekiq.queue_name`
|
699
|
+
```
|
700
|
+
Chewy.settings[:sidekiq] = {queue: :low}
|
701
|
+
```
|
702
|
+
|
635
703
|
#### `:active_job`
|
636
704
|
|
637
705
|
This does the same thing as `:atomic`, but using ActiveJob. This will inherit the ActiveJob configuration settings including the `active_job.queue_adapter` setting for the environment. Patch `Chewy::Strategy::ActiveJob::Worker` for index updates improving.
|
@@ -642,6 +710,21 @@ Chewy.strategy(:active_job) do
|
|
642
710
|
end
|
643
711
|
```
|
644
712
|
|
713
|
+
The default queue name is `chewy`, you can customize it in settings: `active_job.queue_name`
|
714
|
+
```
|
715
|
+
Chewy.settings[:active_job] = {queue: :low}
|
716
|
+
```
|
717
|
+
|
718
|
+
#### `:shoryuken`
|
719
|
+
|
720
|
+
This does the same thing as `:atomic`, but asynchronously using shoryuken. Patch `Chewy::Strategy::Shoryuken::Worker` for index updates improving.
|
721
|
+
|
722
|
+
```ruby
|
723
|
+
Chewy.strategy(:shoryuken) do
|
724
|
+
City.popular.map(&:do_some_update_action!)
|
725
|
+
end
|
726
|
+
```
|
727
|
+
|
645
728
|
#### `:urgent`
|
646
729
|
|
647
730
|
The following strategy is convenient if you are going to update documents in your index one by one.
|
@@ -652,7 +735,7 @@ Chewy.strategy(:urgent) do
|
|
652
735
|
end
|
653
736
|
```
|
654
737
|
|
655
|
-
This code
|
738
|
+
This code will perform `City.popular.count` requests for ES documents update.
|
656
739
|
|
657
740
|
It is convenient for use in e.g. the Rails console with non-block notation:
|
658
741
|
|
@@ -717,570 +800,295 @@ RSpec.configure do |config|
|
|
717
800
|
end
|
718
801
|
```
|
719
802
|
|
720
|
-
###
|
721
|
-
|
722
|
-
```ruby
|
723
|
-
scope = UsersIndex.query(term: {name: 'foo'})
|
724
|
-
.filter(range: {rating: {gte: 100}})
|
725
|
-
.order(created: :desc)
|
726
|
-
.limit(20).offset(100)
|
727
|
-
|
728
|
-
scope.to_a # => will produce array of UserIndex::User or other types instances
|
729
|
-
scope.map { |user| user.email }
|
730
|
-
scope.total_count # => will return total objects count
|
731
|
-
|
732
|
-
scope.per(10).page(3) # supports kaminari pagination
|
733
|
-
scope.explain.map { |user| user._explanation }
|
734
|
-
scope.only(:id, :email) # returns ids and emails only
|
735
|
-
|
736
|
-
scope.merge(other_scope) # queries could be merged
|
737
|
-
```
|
803
|
+
### `ActiveSupport::Notifications` support
|
738
804
|
|
739
|
-
|
805
|
+
Chewy has notifying the following events:
|
740
806
|
|
741
|
-
|
742
|
-
UsersIndex::User.filter(term: {name: 'foo'}) # will return UserIndex::User collection only
|
743
|
-
```
|
807
|
+
#### `search_query.chewy` payload
|
744
808
|
|
745
|
-
|
746
|
-
`
|
809
|
+
* `payload[:index]`: requested index class
|
810
|
+
* `payload[:request]`: request hash
|
747
811
|
|
748
|
-
|
812
|
+
#### `import_objects.chewy` payload
|
749
813
|
|
750
|
-
|
814
|
+
* `payload[:type]`: currently imported type
|
815
|
+
* `payload[:import]`: imports stats, total imported and deleted objects count:
|
751
816
|
|
752
|
-
|
817
|
+
```ruby
|
818
|
+
{index: 30, delete: 5}
|
819
|
+
```
|
753
820
|
|
754
|
-
|
755
|
-
UsersIndex::User.filter{ name == 'Fred' }.filter{ age < 42 } # will be wrapped with `and` filter
|
756
|
-
UsersIndex::User.filter{ name == 'Fred' }.filter{ age < 42 }.filter_mode(:should) # will be wrapped with bool `should` filter
|
757
|
-
UsersIndex::User.filter{ name == 'Fred' }.filter{ age < 42 }.filter_mode('75%') # will be wrapped with bool `should` filter with `minimum_should_match: '75%'`
|
758
|
-
```
|
821
|
+
* `payload[:errors]`: might not exists. Contains grouped errors with objects ids list:
|
759
822
|
|
760
|
-
|
823
|
+
```ruby
|
824
|
+
{index: {
|
825
|
+
'error 1 text' => ['1', '2', '3'],
|
826
|
+
'error 2 text' => ['4']
|
827
|
+
}, delete: {
|
828
|
+
'delete error text' => ['10', '12']
|
829
|
+
}}
|
830
|
+
```
|
761
831
|
|
762
|
-
###
|
832
|
+
### NewRelic integration
|
763
833
|
|
764
|
-
|
834
|
+
To integrate with NewRelic you may use the following example source (config/initializers/chewy.rb):
|
765
835
|
|
766
836
|
```ruby
|
767
|
-
|
768
|
-
UsersIndex::User.delete_all
|
769
|
-
UsersIndex.filter{ age < 42 }.delete_all
|
770
|
-
UsersIndex::User.filter{ age < 42 }.delete_all
|
771
|
-
```
|
837
|
+
require 'new_relic/agent/instrumentation/evented_subscriber'
|
772
838
|
|
773
|
-
|
774
|
-
|
775
|
-
|
839
|
+
class ChewySubscriber < NewRelic::Agent::Instrumentation::EventedSubscriber
|
840
|
+
def start(name, id, payload)
|
841
|
+
event = ChewyEvent.new(name, Time.current, nil, id, payload)
|
842
|
+
push_event(event)
|
843
|
+
end
|
776
844
|
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
```
|
845
|
+
def finish(_name, id, _payload)
|
846
|
+
pop_event(id).finish
|
847
|
+
end
|
781
848
|
|
782
|
-
|
849
|
+
class ChewyEvent < NewRelic::Agent::Instrumentation::Event
|
850
|
+
OPERATIONS = {
|
851
|
+
'import_objects.chewy' => 'import',
|
852
|
+
'search_query.chewy' => 'search',
|
853
|
+
'delete_query.chewy' => 'delete'
|
854
|
+
}.freeze
|
783
855
|
|
784
|
-
*
|
856
|
+
def initialize(*args)
|
857
|
+
super
|
858
|
+
@segment = start_segment
|
859
|
+
end
|
785
860
|
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
861
|
+
def start_segment
|
862
|
+
segment = NewRelic::Agent::Transaction::DatastoreSegment.new product, operation, collection, host, port
|
863
|
+
if (txn = state.current_transaction)
|
864
|
+
segment.transaction = txn
|
865
|
+
end
|
866
|
+
segment.notice_sql @payload[:request].to_s
|
867
|
+
segment.start
|
868
|
+
segment
|
869
|
+
end
|
790
870
|
|
791
|
-
|
792
|
-
|
871
|
+
def finish
|
872
|
+
if (txn = state.current_transaction)
|
873
|
+
txn.add_segment @segment
|
874
|
+
end
|
875
|
+
@segment.finish
|
876
|
+
end
|
793
877
|
|
794
|
-
|
795
|
-
UsersIndex.filter{ name == 'Name' } # simple field term filter
|
796
|
-
UsersIndex.filter{ name(:bool) == ['Name1', 'Name2'] } # terms query with `execution: :bool` option passed
|
797
|
-
UsersIndex.filter{ answers.title =~ /regexp/ } # regexp filter for `answers.title` field
|
798
|
-
```
|
878
|
+
private
|
799
879
|
|
800
|
-
|
880
|
+
def state
|
881
|
+
@state ||= NewRelic::Agent::TransactionState.tl_get
|
882
|
+
end
|
801
883
|
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
must(
|
806
|
-
should(name =~ 'Fr').should_not(name == 'Fred') & (age == 42), email =~ /gmail\.com/
|
807
|
-
) | ((roles.admin == true) & name?)
|
808
|
-
} # many of the combination possibilities
|
809
|
-
```
|
884
|
+
def product
|
885
|
+
'Elasticsearch'
|
886
|
+
end
|
810
887
|
|
811
|
-
|
888
|
+
def operation
|
889
|
+
OPERATIONS[name]
|
890
|
+
end
|
812
891
|
|
813
|
-
|
814
|
-
|
815
|
-
|
892
|
+
def collection
|
893
|
+
payload.values_at(:type, :index)
|
894
|
+
.reject { |value| value.try(:empty?) }
|
895
|
+
.first
|
896
|
+
.to_s
|
897
|
+
end
|
816
898
|
|
817
|
-
|
818
|
-
|
819
|
-
|
899
|
+
def host
|
900
|
+
Chewy.client.transport.hosts.first[:host]
|
901
|
+
end
|
820
902
|
|
821
|
-
|
822
|
-
|
823
|
-
|
903
|
+
def port
|
904
|
+
Chewy.client.transport.hosts.first[:port]
|
905
|
+
end
|
906
|
+
end
|
907
|
+
end
|
824
908
|
|
825
|
-
|
826
|
-
UsersIndex.filter{ name(cache: 'name_regexp') =~ /Name/ }
|
827
|
-
# Or not
|
828
|
-
UsersIndex.filter{ name(cache: true) =~ /Name/ }
|
909
|
+
ActiveSupport::Notifications.subscribe(/.chewy$/, ChewySubscriber.new)
|
829
910
|
```
|
830
911
|
|
831
|
-
|
832
|
-
|
833
|
-
* Term filter
|
834
|
-
|
835
|
-
```json
|
836
|
-
{"term": {"name": "Fred"}}
|
837
|
-
{"not": {"term": {"name": "Johny"}}}
|
838
|
-
```
|
839
|
-
|
840
|
-
```ruby
|
841
|
-
UsersIndex.filter{ name == 'Fred' }
|
842
|
-
UsersIndex.filter{ name != 'Johny' }
|
843
|
-
```
|
844
|
-
|
845
|
-
* Terms filter
|
846
|
-
|
847
|
-
```json
|
848
|
-
{"terms": {"name": ["Fred", "Johny"]}}
|
849
|
-
{"not": {"terms": {"name": ["Fred", "Johny"]}}}
|
850
|
-
|
851
|
-
{"terms": {"name": ["Fred", "Johny"], "execution": "or"}}
|
852
|
-
|
853
|
-
{"terms": {"name": ["Fred", "Johny"], "execution": "and"}}
|
854
|
-
|
855
|
-
{"terms": {"name": ["Fred", "Johny"], "execution": "bool"}}
|
856
|
-
|
857
|
-
{"terms": {"name": ["Fred", "Johny"], "execution": "fielddata"}}
|
858
|
-
```
|
859
|
-
|
860
|
-
```ruby
|
861
|
-
UsersIndex.filter{ name == ['Fred', 'Johny'] }
|
862
|
-
UsersIndex.filter{ name != ['Fred', 'Johny'] }
|
863
|
-
|
864
|
-
UsersIndex.filter{ name(:|) == ['Fred', 'Johny'] }
|
865
|
-
UsersIndex.filter{ name(:or) == ['Fred', 'Johny'] }
|
866
|
-
UsersIndex.filter{ name(execution: :or) == ['Fred', 'Johny'] }
|
867
|
-
|
868
|
-
UsersIndex.filter{ name(:&) == ['Fred', 'Johny'] }
|
869
|
-
UsersIndex.filter{ name(:and) == ['Fred', 'Johny'] }
|
870
|
-
UsersIndex.filter{ name(execution: :and) == ['Fred', 'Johny'] }
|
871
|
-
|
872
|
-
UsersIndex.filter{ name(:b) == ['Fred', 'Johny'] }
|
873
|
-
UsersIndex.filter{ name(:bool) == ['Fred', 'Johny'] }
|
874
|
-
UsersIndex.filter{ name(execution: :bool) == ['Fred', 'Johny'] }
|
875
|
-
|
876
|
-
UsersIndex.filter{ name(:f) == ['Fred', 'Johny'] }
|
877
|
-
UsersIndex.filter{ name(:fielddata) == ['Fred', 'Johny'] }
|
878
|
-
UsersIndex.filter{ name(execution: :fielddata) == ['Fred', 'Johny'] }
|
879
|
-
```
|
880
|
-
|
881
|
-
* Regexp filter (== and =~ are equivalent)
|
882
|
-
|
883
|
-
```json
|
884
|
-
{"regexp": {"name.first": "s.*y"}}
|
885
|
-
|
886
|
-
{"not": {"regexp": {"name.first": "s.*y"}}}
|
887
|
-
|
888
|
-
{"regexp": {"name.first": {"value": "s.*y", "flags": "ANYSTRING|INTERSECTION"}}}
|
889
|
-
```
|
890
|
-
|
891
|
-
```ruby
|
892
|
-
UsersIndex.filter{ name.first == /s.*y/ }
|
893
|
-
UsersIndex.filter{ name.first =~ /s.*y/ }
|
894
|
-
|
895
|
-
UsersIndex.filter{ name.first != /s.*y/ }
|
896
|
-
UsersIndex.filter{ name.first !~ /s.*y/ }
|
897
|
-
|
898
|
-
UsersIndex.filter{ name.first(:anystring, :intersection) == /s.*y/ }
|
899
|
-
UsersIndex.filter{ name.first(flags: [:anystring, :intersection]) == /s.*y/ }
|
900
|
-
```
|
901
|
-
|
902
|
-
* Prefix filter
|
903
|
-
|
904
|
-
```json
|
905
|
-
{"prefix": {"name": "Fre"}}
|
906
|
-
{"not": {"prefix": {"name": "Joh"}}}
|
907
|
-
```
|
908
|
-
|
909
|
-
```ruby
|
910
|
-
UsersIndex.filter{ name =~ re' }
|
911
|
-
UsersIndex.filter{ name !~ 'Joh' }
|
912
|
-
```
|
913
|
-
|
914
|
-
* Exists filter
|
915
|
-
|
916
|
-
```json
|
917
|
-
{"exists": {"field": "name"}}
|
918
|
-
```
|
919
|
-
|
920
|
-
```ruby
|
921
|
-
UsersIndex.filter{ name? }
|
922
|
-
UsersIndex.filter{ !!name }
|
923
|
-
UsersIndex.filter{ !!name? }
|
924
|
-
UsersIndex.filter{ name != nil }
|
925
|
-
UsersIndex.filter{ !(name == nil) }
|
926
|
-
```
|
927
|
-
|
928
|
-
* Missing filter
|
929
|
-
|
930
|
-
```json
|
931
|
-
{"missing": {"field": "name", "existence": true, "null_value": false}}
|
932
|
-
{"missing": {"field": "name", "existence": true, "null_value": true}}
|
933
|
-
{"missing": {"field": "name", "existence": false, "null_value": true}}
|
934
|
-
```
|
935
|
-
|
936
|
-
```ruby
|
937
|
-
UsersIndex.filter{ !name }
|
938
|
-
UsersIndex.filter{ !name? }
|
939
|
-
UsersIndex.filter{ name == nil }
|
940
|
-
```
|
941
|
-
|
942
|
-
* Range
|
943
|
-
|
944
|
-
```json
|
945
|
-
{"range": {"age": {"gt": 42}}}
|
946
|
-
{"range": {"age": {"gte": 42}}}
|
947
|
-
{"range": {"age": {"lt": 42}}}
|
948
|
-
{"range": {"age": {"lte": 42}}}
|
949
|
-
|
950
|
-
{"range": {"age": {"gt": 40, "lt": 50}}}
|
951
|
-
{"range": {"age": {"gte": 40, "lte": 50}}}
|
952
|
-
|
953
|
-
{"range": {"age": {"gt": 40, "lte": 50}}}
|
954
|
-
{"range": {"age": {"gte": 40, "lt": 50}}}
|
955
|
-
```
|
956
|
-
|
957
|
-
```ruby
|
958
|
-
UsersIndex.filter{ age > 42 }
|
959
|
-
UsersIndex.filter{ age >= 42 }
|
960
|
-
UsersIndex.filter{ age < 42 }
|
961
|
-
UsersIndex.filter{ age <= 42 }
|
962
|
-
|
963
|
-
UsersIndex.filter{ age == (40..50) }
|
964
|
-
UsersIndex.filter{ (age > 40) & (age < 50) }
|
965
|
-
UsersIndex.filter{ age == [40..50] }
|
966
|
-
UsersIndex.filter{ (age >= 40) & (age <= 50) }
|
967
|
-
|
968
|
-
UsersIndex.filter{ (age > 40) & (age <= 50) }
|
969
|
-
UsersIndex.filter{ (age >= 40) & (age < 50) }
|
970
|
-
```
|
971
|
-
|
972
|
-
* Bool filter
|
973
|
-
|
974
|
-
```json
|
975
|
-
{"bool": {
|
976
|
-
"must": [{"term": {"name": "Name"}}],
|
977
|
-
"should": [{"term": {"age": 42}}, {"term": {"age": 45}}]
|
978
|
-
}}
|
979
|
-
```
|
980
|
-
|
981
|
-
```ruby
|
982
|
-
UsersIndex.filter{ must(name == 'Name').should(age == 42, age == 45) }
|
983
|
-
```
|
984
|
-
|
985
|
-
* And filter
|
986
|
-
|
987
|
-
```json
|
988
|
-
{"and": [{"term": {"name": "Name"}}, {"range": {"age": {"lt": 42}}}]}
|
989
|
-
```
|
990
|
-
|
991
|
-
```ruby
|
992
|
-
UsersIndex.filter{ (name == 'Name') & (age < 42) }
|
993
|
-
```
|
994
|
-
|
995
|
-
* Or filter
|
996
|
-
|
997
|
-
```json
|
998
|
-
{"or": [{"term": {"name": "Name"}}, {"range": {"age": {"lt": 42}}}]}
|
999
|
-
```
|
1000
|
-
|
1001
|
-
```ruby
|
1002
|
-
UsersIndex.filter{ (name == 'Name') | (age < 42) }
|
1003
|
-
```
|
1004
|
-
|
1005
|
-
```json
|
1006
|
-
{"not": {"term": {"name": "Name"}}}
|
1007
|
-
{"not": {"range": {"age": {"lt": 42}}}}
|
1008
|
-
```
|
912
|
+
### Search requests
|
1009
913
|
|
1010
|
-
|
1011
|
-
UsersIndex.filter{ !(name == 'Name') } # or UsersIndex.filter{ name != 'Name' }
|
1012
|
-
UsersIndex.filter{ !(age < 42) }
|
1013
|
-
```
|
914
|
+
Long story short: there is a new DSL that supports ES2 and ES5, the previous DSL version (which supports ES1 and ES2) documentation was moved to [LEGACY_DSL.md](LEGACY_DSL.md).
|
1014
915
|
|
1015
|
-
|
916
|
+
If you want to use the old DSL - simply do `Chewy.search_class = Chewy::Query` somewhere before indices are initialized.
|
1016
917
|
|
1017
|
-
|
1018
|
-
{"match_all": {}}
|
1019
|
-
```
|
918
|
+
The new DSL is enabled by default, here is a quick introduction.
|
1020
919
|
|
1021
|
-
|
1022
|
-
UsersIndex.filter{ match_all }
|
1023
|
-
```
|
920
|
+
#### Composing requests
|
1024
921
|
|
1025
|
-
|
922
|
+
The request DSL have the same chainable nature as AR or Mongoid ones. The main class is `Chewy::Search::Request`. It is possible to perform requests on behalf of indices or types:
|
1026
923
|
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
```ruby
|
1033
|
-
UsersIndex.filter{ has_child(:blog_tag).query(term: {tag: 'something'}) }
|
1034
|
-
UsersIndex.filter{ has_child(:comment).filter{ user == 'john' } }
|
1035
|
-
```
|
1036
|
-
|
1037
|
-
* Has parent filter
|
1038
|
-
|
1039
|
-
```json
|
1040
|
-
{"has_parent": {"type": "blog", "query": {"term": {"tag": "something"}}}}
|
1041
|
-
{"has_parent": {"type": "blog", "filter": {"term": {"text": "bonsai three"}}}}
|
1042
|
-
```
|
924
|
+
```ruby
|
925
|
+
PlaceIndex.query(match: {name: 'London'}) # returns documents of any type
|
926
|
+
PlaceIndex::City.query(match: {name: 'London'}) # returns cities only.
|
927
|
+
```
|
1043
928
|
|
1044
|
-
|
1045
|
-
UsersIndex.filter{ has_parent(:blog).query(term: {tag: 'something'}) }
|
1046
|
-
UsersIndex.filter{ has_parent(:blog).filter{ text == 'bonsai three' } }
|
1047
|
-
```
|
929
|
+
Main methods of the request DSL are: `query`, `filter` and `post_filter`, it is possible to pass pure query hashes or use `elasticsearch-dsl`. Also, there is an additional
|
1048
930
|
|
1049
|
-
|
931
|
+
```ruby
|
932
|
+
PlaceIndex
|
933
|
+
.filter(term: {name: 'Bangkok'})
|
934
|
+
.query { match name: 'London' }
|
935
|
+
.query.not(range: {population: {gt: 1_000_000}})
|
936
|
+
```
|
1050
937
|
|
1051
|
-
|
938
|
+
See https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html and https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl for more details.
|
1052
939
|
|
1053
|
-
|
940
|
+
An important part of requests manipulation is merging. There are 4 methods to perform it: `merge`, `and`, `or`, `not`. See [Chewy::Search::QueryProxy](lib/chewy/search/query_proxy.rb) for details. Also, `only` and `except` methods help to remove unneeded parts of the request.
|
1054
941
|
|
1055
|
-
|
942
|
+
Every other request part is covered by a bunch of additional methods, see [Chewy::Search::Request](lib/chewy/search/request.rb) for details:
|
1056
943
|
|
1057
944
|
```ruby
|
1058
|
-
|
945
|
+
PlaceIndex.limit(10).offset(30).order(:name, {population: {order: :desc}})
|
1059
946
|
```
|
1060
947
|
|
1061
|
-
|
948
|
+
Request DSL also provides additional scope actions, like `delete_all`, `exists?`, `count`, `pluck`, etc.
|
1062
949
|
|
1063
|
-
|
950
|
+
#### Pagination
|
1064
951
|
|
1065
|
-
|
1066
|
-
< { ... ,"facets":{"countries":{"_type":"terms","missing":?,"total":?,"other":?,"terms":[{"term":"USA","count":?},{"term":"Brazil","count":?}, ...}}
|
1067
|
-
```
|
952
|
+
The request DSL supports pagination with `Kaminari` and `WillPaginate`. An appropriate extension is enabled on initializtion if any of libraries is available. See [Chewy::Search](lib/chewy/search.rb) and [Chewy::Search::Pagination](lib/chewy/search/pagination/) namespace for details.
|
1068
953
|
|
1069
|
-
|
954
|
+
#### Named scopes
|
1070
955
|
|
1071
|
-
|
956
|
+
Chewy supports named scopes functionality. There is no specialized DSL for named scopes definition, it is simply about defining class methods.
|
1072
957
|
|
1073
|
-
|
958
|
+
See [Chewy::Search::Scoping](lib/chewy/search/scoping.rb) for details.
|
1074
959
|
|
1075
|
-
|
960
|
+
#### Scroll API
|
1076
961
|
|
1077
|
-
|
1078
|
-
class UsersIndex < Chewy::Index
|
1079
|
-
define_type User do
|
1080
|
-
field :name
|
1081
|
-
field :rating
|
1082
|
-
end
|
1083
|
-
end
|
1084
|
-
|
1085
|
-
all_johns = UsersIndex::User.filter { name == 'john' }.aggs({ avg_rating: { avg: { field: 'rating' } } })
|
962
|
+
ElasticSearch scroll API is utilized by a bunch of methods: `scroll_batches`, `scroll_hits`, `scroll_wrappers` and `scroll_objects`.
|
1086
963
|
|
1087
|
-
|
1088
|
-
# => {"avg_rating"=>{"value"=>3.5}}
|
1089
|
-
```
|
964
|
+
See [Chewy::Search::Scrolling](lib/chewy/search/scrolling.rb) for details.
|
1090
965
|
|
1091
|
-
|
1092
|
-
which is also available under the .agg alias method.
|
966
|
+
#### Loading objects
|
1093
967
|
|
1094
|
-
|
968
|
+
It is possible to load ORM/ODM source objects with the `objects` method. To provide additional loading options use `load` method:
|
1095
969
|
|
1096
970
|
```ruby
|
1097
|
-
|
1098
|
-
|
1099
|
-
field :name
|
1100
|
-
field :rating, type: "long"
|
1101
|
-
agg :avg_rating do
|
1102
|
-
{ avg: { field: 'rating' } }
|
1103
|
-
end
|
1104
|
-
end
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
all_johns = UsersIndex::User.filter { name == 'john' }.aggs(:avg_rating)
|
1108
|
-
|
1109
|
-
avg_johns_rating = all_johns.aggs
|
1110
|
-
# => {"avg_rating"=>{"value"=>3.5}}
|
971
|
+
PlacesIndex.load(scope: -> { active }).to_a # to_a returns `Chewy::Type` wrappers.
|
972
|
+
PlacesIndex.load(scope: -> { active }).objects # An array of AR source objects.
|
1111
973
|
```
|
1112
974
|
|
1113
|
-
|
1114
|
-
with the same name. To explicitly reference an aggregation you provide a string to the #aggs method of the form:
|
1115
|
-
`index_name#document_type.aggregation_name`
|
975
|
+
See [Chewy::Search::Loader](lib/chewy/search/loader.rb) for more details.
|
1116
976
|
|
1117
|
-
|
977
|
+
In case when it is necessary to iterate through both of the wrappers and objects simultaneously, `object_hash` method helps a lot:
|
1118
978
|
|
1119
979
|
```ruby
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
field :rating, type: "long"
|
1124
|
-
agg :avg_rating do
|
1125
|
-
{ avg: { field: 'rating' } }
|
1126
|
-
end
|
1127
|
-
end
|
1128
|
-
define_type Post do
|
1129
|
-
field :title
|
1130
|
-
field :body
|
1131
|
-
field :comments do
|
1132
|
-
field :message
|
1133
|
-
field :rating, type: "long"
|
1134
|
-
end
|
1135
|
-
agg :avg_rating do
|
1136
|
-
{ avg: { field: 'comments.rating' } }
|
1137
|
-
end
|
1138
|
-
end
|
980
|
+
scope = PlacesIndex.load(scope: -> { active })
|
981
|
+
scope.each do |wrapper|
|
982
|
+
scope.object_hash[wrapper]
|
1139
983
|
end
|
1140
|
-
|
1141
|
-
all_docs = UsersIndex.filter {match_all}.aggs("users#user.avg_rating")
|
1142
|
-
all_docs.aggs
|
1143
|
-
# => {"users#user.avg_rating"=>{"value"=>3.5}}
|
1144
984
|
```
|
1145
985
|
|
1146
|
-
|
986
|
+
#### Legacy DSL incompatibilities
|
1147
987
|
|
1148
|
-
|
988
|
+
* Filters advanced block DSL is not supported anymore, `elasticsearch-dsl` is used instead.
|
989
|
+
* Things like `query_mode` and `filter_mode` are in past, use advanced DSL to achieve similar behavior. See [Chewy::Search::QueryProxy](lib/chewy/search/query_proxy.rb) for details.
|
990
|
+
* `preload` method is no more, the collection returned by scope doesn't depend on loading options, scope always returns `Chewy::Type` wrappers. To get ORM/ODM objects, use `#objects` method.
|
991
|
+
* Some of the methods have changed their purpose: `only` was used to filter fields before, now it filters the scope. To filter fields use `source` or `stored_fields`.
|
992
|
+
* `types!` method is no more, use `except(:types).types(...)`
|
993
|
+
* Named aggregations are not supported, use named scopes instead.
|
994
|
+
* A lot of query-level methods were not ported: everything that is related to boost and scoring. Use `query` manipulation to provide them.
|
995
|
+
* `Chewy::Type#_object` returns nil always. Use `Chewy::Search::Response#object_hash` instead.
|
1149
996
|
|
1150
|
-
|
1151
|
-
UsersIndex.script_fields(
|
1152
|
-
distance: {
|
1153
|
-
params: {
|
1154
|
-
lat: 37.569976,
|
1155
|
-
lon: -122.351591
|
1156
|
-
},
|
1157
|
-
script: "doc['coordinates'].distanceInMiles(lat, lon)"
|
1158
|
-
}
|
1159
|
-
)
|
1160
|
-
```
|
1161
|
-
Here, `coordinates` is a field with type `geo_point`. There will be a `distance` field for the index's model in the search result.
|
997
|
+
### Rake tasks
|
1162
998
|
|
1163
|
-
|
999
|
+
For a Rails application, some index-maintaining rake tasks are defined.
|
1164
1000
|
|
1165
|
-
|
1001
|
+
#### `chewy:reset`
|
1166
1002
|
|
1167
|
-
|
1168
|
-
|
1003
|
+
Performs zero-downtime reindexing as described [here](https://www.elastic.co/blog/changing-mapping-with-zero-downtime). So the rake task creates a new index with unique suffix and then simply aliases it to the common index name. The previous index is deleted afterwards (see `Chewy::Index.reset!` for more details).
|
1004
|
+
|
1005
|
+
```bash
|
1006
|
+
rake chewy:reset # resets all the existing indices
|
1007
|
+
rake chewy:reset[users] # resets UsersIndex only
|
1008
|
+
rake chewy:reset[users,places] # resets UsersIndex and PlacesIndex
|
1009
|
+
rake chewy:reset[-users,places] # resets every index in the application except specified ones
|
1169
1010
|
```
|
1170
1011
|
|
1171
|
-
|
1012
|
+
#### `chewy:upgrade`
|
1172
1013
|
|
1173
|
-
|
1014
|
+
Performs reset exactly the same way as `chewy:reset` does, but only when the index specification (setting or mapping) was changed.
|
1174
1015
|
|
1175
|
-
|
1176
|
-
UsersIndex.boost_factor(5, filter: {term: {type: 'Expert'}})
|
1177
|
-
```
|
1016
|
+
It works only when index specification is locked in `Chewy::Stash::Specification` index. The first run will reset all indexes and lock their specifications.
|
1178
1017
|
|
1179
|
-
|
1018
|
+
See [Chewy::Stash::Specification](lib/chewy/stash.rb) and [Chewy::Index::Specification](lib/chewy/index/specification.rb) for more details.
|
1180
1019
|
|
1181
|
-
It is possible to load source objects from the database for every search result:
|
1182
1020
|
|
1183
|
-
```
|
1184
|
-
|
1021
|
+
```bash
|
1022
|
+
rake chewy:upgrade # upgrades all the existing indices
|
1023
|
+
rake chewy:upgrade[users] # upgrades UsersIndex only
|
1024
|
+
rake chewy:upgrade[users,places] # upgrades UsersIndex and PlacesIndex
|
1025
|
+
rake chewy:upgrade[-users,places] # upgrades every index in the application except specified ones
|
1026
|
+
```
|
1185
1027
|
|
1186
|
-
|
1187
|
-
scope.load.query(...) # => since objects are loaded lazily you can complete scope
|
1188
|
-
scope.load(user: { scope: ->{ includes(:country) }}) # you can also pass loading scopes for each
|
1189
|
-
# possibly returned type
|
1190
|
-
scope.load(user: { scope: User.includes(:country) }) # the second scope passing way.
|
1191
|
-
scope.load(scope: ->{ includes(:country) }) # and more common scope applied to every loaded object type.
|
1028
|
+
#### `chewy:update`
|
1192
1029
|
|
1193
|
-
|
1194
|
-
```
|
1030
|
+
It doesn't create indexes, it simply imports everything to the existing ones and fails if the index was not created before.
|
1195
1031
|
|
1196
|
-
|
1032
|
+
Unlike `reset` or `upgrade` tasks, it is possible to pass type references to update the particular type. In index name is passed without the type specified, it will update all the types defined for this index.
|
1197
1033
|
|
1198
|
-
```
|
1199
|
-
|
1034
|
+
```bash
|
1035
|
+
rake chewy:update # updates all the existing indices
|
1036
|
+
rake chewy:update[users] # updates UsersIndex only
|
1037
|
+
rake chewy:update[users,places#city] # updates the whole UsersIndex and PlacesIndex::City type
|
1038
|
+
rake chewy:update[-users,places#city] # updates every index in the application except every type defined in UsersIndex and the rest of the types defined in PlacesIndex
|
1200
1039
|
```
|
1201
1040
|
|
1202
|
-
|
1041
|
+
#### `chewy:sync`
|
1203
1042
|
|
1204
|
-
|
1043
|
+
Provides a way to synchronize outdated indexes with the source quickly and without doing a full reset.
|
1205
1044
|
|
1206
|
-
|
1045
|
+
Arguments are similar to the ones taken by `chewy:update` task. It is possible to specify a particular type or a whole index.
|
1207
1046
|
|
1208
|
-
|
1047
|
+
See [Chewy::Type::Syncer](lib/chewy/type/syncer.rb) for more details.
|
1209
1048
|
|
1210
|
-
|
1211
|
-
|
1049
|
+
```bash
|
1050
|
+
rake chewy:sync # synchronizes all the existing indices
|
1051
|
+
rake chewy:sync[users] # synchronizes UsersIndex only
|
1052
|
+
rake chewy:sync[users,places#city] # synchronizes the whole UsersIndex and PlacesIndex::City type
|
1053
|
+
rake chewy:sync[-users,places#city] # synchronizes every index in the application except every type defined in UsersIndex and the rest of the types defined in PlacesIndex
|
1054
|
+
```
|
1212
1055
|
|
1213
|
-
#### `
|
1056
|
+
#### `chewy:deploy`
|
1214
1057
|
|
1215
|
-
|
1216
|
-
* `payload[:import]`: imports stats, total imported and deleted objects count:
|
1058
|
+
This rake task is especially useful during the production deploy. It is a combination of `chewy:upgrade` and `chewy:sync` and the latter is called only for the indexes that were not reset during the first stage.
|
1217
1059
|
|
1218
|
-
|
1219
|
-
{index: 30, delete: 5}
|
1220
|
-
```
|
1060
|
+
It is not possible to specify any particular types/indexes for this task as it doesn't make much sense.
|
1221
1061
|
|
1222
|
-
|
1062
|
+
Right now the approach is that if some data had been updated, but index definition was not changed (no changes satisfying the synchronization algorithm were done), it would be much faster to perform manual partial index update inside data migrations or even manually after the deploy.
|
1223
1063
|
|
1224
|
-
|
1225
|
-
{index: {
|
1226
|
-
'error 1 text' => ['1', '2', '3'],
|
1227
|
-
'error 2 text' => ['4']
|
1228
|
-
}, delete: {
|
1229
|
-
'delete error text' => ['10', '12']
|
1230
|
-
}}
|
1231
|
-
```
|
1064
|
+
Also, there is always full reset alternative with `rake chewy:reset`.
|
1232
1065
|
|
1233
|
-
####
|
1066
|
+
#### Parallelizing rake tasks
|
1234
1067
|
|
1235
|
-
|
1068
|
+
Every task described above has its own parallel version. Every parallel rake task takes the number for processes for execution as the first argument and the rest of the arguments are exactly the same as for the non-parallel task version.
|
1236
1069
|
|
1237
|
-
|
1238
|
-
ActiveSupport::Notifications.subscribe('import_objects.chewy') do |name, start, finish, id, payload|
|
1239
|
-
metric_name = "Database/ElasticSearch/import"
|
1240
|
-
duration = (finish - start).to_f
|
1241
|
-
logged = "#{payload[:type]} #{payload[:import].to_a.map{ |i| i.join(':') }.join(', ')}"
|
1242
|
-
|
1243
|
-
self.class.trace_execution_scoped([metric_name]) do
|
1244
|
-
NewRelic::Agent.instance.transaction_sampler.notice_sql(logged, nil, duration)
|
1245
|
-
NewRelic::Agent.instance.sql_sampler.notice_sql(logged, metric_name, nil, duration)
|
1246
|
-
NewRelic::Agent.record_metric(metric_name, duration)
|
1247
|
-
end
|
1248
|
-
end
|
1070
|
+
[https://github.com/grosser/parallel](https://github.com/grosser/parallel) gem is required to use these tasks.
|
1249
1071
|
|
1250
|
-
|
1251
|
-
metric_name = "Database/ElasticSearch/search"
|
1252
|
-
duration = (finish - start).to_f
|
1253
|
-
logged = "#{payload[:type].presence || payload[:index]} #{payload[:request]}"
|
1072
|
+
If the number of processes is not specified explicitly - `parallel` gem tries to automatically derive the number of processes to use.
|
1254
1073
|
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1074
|
+
```bash
|
1075
|
+
rake chewy:parallel:reset
|
1076
|
+
rake chewy:parallel:upgrade[4]
|
1077
|
+
rake chewy:parallel:update[4,places#city]
|
1078
|
+
rake chewy:parallel:sync[4,-users]
|
1079
|
+
rake chewy:parallel:deploy[4] # performs parallel upgrade and parallel sync afterwards
|
1261
1080
|
```
|
1262
1081
|
|
1263
|
-
|
1082
|
+
#### `chewy:journal`
|
1264
1083
|
|
1265
|
-
|
1084
|
+
This namespace contains two tasks for the journal manipulations: `chewy:journal:apply` and `chewy:journal:clean`. Both are taking time as the first argument (optional for clean) and a list of indexes/types exactly as the tasks above. Time can be in any format parsable by ActiveSupport.
|
1266
1085
|
|
1267
1086
|
```bash
|
1268
|
-
rake chewy:
|
1269
|
-
rake chewy:
|
1270
|
-
rake chewy:reset[users,projects] # resets UsersIndex and ProjectsIndex
|
1271
|
-
rake chewy:reset[-users,projects] # resets every index in application except specified ones
|
1272
|
-
|
1273
|
-
rake chewy:update # updates all the existing indices, declared in app/chewy
|
1274
|
-
rake chewy:update[users] # updates UsersIndex only
|
1275
|
-
rake chewy:update[users,projects] # updates UsersIndex and ProjectsIndex
|
1276
|
-
rake chewy:update[-users,projects] # updates every index in application except specified ones
|
1277
|
-
|
1087
|
+
rake chewy:journal:apply["$(date -v-1H -u +%FT%TZ)"] # apply journaled changes for the past hour
|
1088
|
+
rake chewy:journal:apply["$(date -v-1H -u +%FT%TZ)",users] # apply journaled changes for the past hour on UsersIndex only
|
1278
1089
|
```
|
1279
1090
|
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
### Rspec integration
|
1091
|
+
### RSpec integration
|
1284
1092
|
|
1285
1093
|
Just add `require 'chewy/rspec'` to your spec_helper.rb and you will get additional features: See [update_index.rb](lib/chewy/rspec/update_index.rb) for more details.
|
1286
1094
|
|
@@ -1288,22 +1096,19 @@ Just add `require 'chewy/rspec'` to your spec_helper.rb and you will get additio
|
|
1288
1096
|
|
1289
1097
|
Add `require 'chewy/minitest'` to your test_helper.rb, and then for tests which you'd like indexing test hooks, `include Chewy::Minitest::Helpers`.
|
1290
1098
|
|
1099
|
+
Since you can set `:bypass` strategy for test suites and manually handle import for the index and manually flush test indices using `Chewy.massacre`. This will help reduce unnecessary ES requests
|
1100
|
+
|
1101
|
+
But if you require chewy to index/update model regularly in your test suite then you can specify `:urgent` strategy for documents indexing. Add `Chewy.strategy(:urgent)` to test_helper.rb.
|
1102
|
+
|
1291
1103
|
### DatabaseCleaner
|
1292
1104
|
|
1293
|
-
If you use `DatabaseCleaner` in your tests with [the `transaction` strategy](https://github.com/DatabaseCleaner/database_cleaner#how-to-use), you may run into the problem that `ActiveRecord`'s models are not indexed automatically on save despite the fact that you set the callbacks to do this with the `update_index` method. The issue arises because `chewy`
|
1105
|
+
If you use `DatabaseCleaner` in your tests with [the `transaction` strategy](https://github.com/DatabaseCleaner/database_cleaner#how-to-use), you may run into the problem that `ActiveRecord`'s models are not indexed automatically on save despite the fact that you set the callbacks to do this with the `update_index` method. The issue arises because `chewy` indices data on `after_commit` run as default, but all `after_commit` callbacks are not run with the `DatabaseCleaner`'s' `transaction` strategy. You can solve this issue by changing the `Chewy.use_after_commit_callbacks` option. Just add the following initializer in your Rails application:
|
1294
1106
|
|
1295
1107
|
```ruby
|
1296
1108
|
#config/initializers/chewy.rb
|
1297
1109
|
Chewy.use_after_commit_callbacks = !Rails.env.test?
|
1298
1110
|
```
|
1299
1111
|
|
1300
|
-
## TODO a.k.a coming soon:
|
1301
|
-
|
1302
|
-
* Typecasting support
|
1303
|
-
* Advanced (simplified) query DSL: `UsersIndex.query { email == 'my@gmail.com' }` will produce term query
|
1304
|
-
* update_all support
|
1305
|
-
* Maybe, closer ORM/ODM integration, creating index classes implicitly
|
1306
|
-
|
1307
1112
|
## Contributing
|
1308
1113
|
|
1309
1114
|
1. Fork it (http://github.com/toptal/chewy/fork)
|
@@ -1319,3 +1124,8 @@ Use the following Rake tasks to control the Elasticsearch cluster while developi
|
|
1319
1124
|
rake elasticsearch:start # start Elasticsearch cluster on 9250 port for tests
|
1320
1125
|
rake elasticsearch:stop # stop Elasticsearch
|
1321
1126
|
```
|
1127
|
+
|
1128
|
+
## Copyright
|
1129
|
+
|
1130
|
+
Copyright (c) 2013-2021 Toptal, LLC. See [LICENSE.txt](LICENSE.txt) for
|
1131
|
+
further details.
|