chewy 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +30 -16
- data/lib/chewy/errors.rb +3 -0
- data/lib/chewy/fields/root.rb +3 -3
- data/lib/chewy/index/crutch.rb +12 -2
- data/lib/chewy/index/import/bulk_builder.rb +4 -3
- data/lib/chewy/index/import/routine.rb +2 -1
- data/lib/chewy/index/import.rb +4 -4
- data/lib/chewy/index/witchcraft.rb +24 -8
- data/lib/chewy/multi_search.rb +1 -1
- data/lib/chewy/search/parameters/runtime_mappings.rb +14 -0
- data/lib/chewy/search/request.rb +18 -2
- data/lib/chewy/search/scrolling.rb +14 -6
- data/lib/chewy/stash.rb +10 -6
- data/lib/chewy/version.rb +1 -1
- metadata +5 -131
- data/.github/CODEOWNERS +0 -1
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -39
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -16
- data/.github/dependabot.yml +0 -42
- data/.github/workflows/ruby.yml +0 -61
- data/.gitignore +0 -22
- data/.rspec +0 -2
- data/.rubocop.yml +0 -64
- data/.rubocop_todo.yml +0 -225
- data/.yardopts +0 -5
- data/CODE_OF_CONDUCT.md +0 -14
- data/CONTRIBUTING.md +0 -63
- data/Gemfile +0 -22
- data/Guardfile +0 -25
- data/Rakefile +0 -17
- data/chewy.gemspec +0 -24
- data/docker-compose.yml +0 -14
- data/docs/README.md +0 -16
- data/docs/configuration.md +0 -440
- data/docs/import.md +0 -122
- data/docs/indexing.md +0 -329
- data/docs/querying.md +0 -72
- data/docs/rake_tasks.md +0 -108
- data/docs/testing.md +0 -41
- data/docs/troubleshooting.md +0 -101
- data/filters +0 -78
- data/gemfiles/base.gemfile +0 -12
- data/gemfiles/rails.7.2.activerecord.gemfile +0 -14
- data/gemfiles/rails.8.0.activerecord.gemfile +0 -14
- data/migration_guide.md +0 -56
- data/spec/chewy/config_spec.rb +0 -110
- data/spec/chewy/elastic_client_spec.rb +0 -26
- data/spec/chewy/fields/base_spec.rb +0 -700
- data/spec/chewy/fields/root_spec.rb +0 -142
- data/spec/chewy/fields/time_fields_spec.rb +0 -28
- data/spec/chewy/index/actions_spec.rb +0 -851
- data/spec/chewy/index/adapter/active_record_spec.rb +0 -663
- data/spec/chewy/index/adapter/object_spec.rb +0 -243
- data/spec/chewy/index/aliases_spec.rb +0 -49
- data/spec/chewy/index/import/bulk_builder_spec.rb +0 -494
- data/spec/chewy/index/import/bulk_request_spec.rb +0 -95
- data/spec/chewy/index/import/journal_builder_spec.rb +0 -87
- data/spec/chewy/index/import/routine_spec.rb +0 -110
- data/spec/chewy/index/import_spec.rb +0 -615
- data/spec/chewy/index/mapping_spec.rb +0 -135
- data/spec/chewy/index/observe/active_record_methods_spec.rb +0 -68
- data/spec/chewy/index/observe/callback_spec.rb +0 -139
- data/spec/chewy/index/observe_spec.rb +0 -143
- data/spec/chewy/index/settings_spec.rb +0 -136
- data/spec/chewy/index/specification_spec.rb +0 -156
- data/spec/chewy/index/syncer_spec.rb +0 -118
- data/spec/chewy/index/witchcraft_spec.rb +0 -245
- data/spec/chewy/index/wrapper_spec.rb +0 -100
- data/spec/chewy/index_spec.rb +0 -269
- data/spec/chewy/journal_spec.rb +0 -223
- data/spec/chewy/minitest/helpers_spec.rb +0 -194
- data/spec/chewy/minitest/search_index_receiver_spec.rb +0 -120
- data/spec/chewy/multi_search_spec.rb +0 -84
- data/spec/chewy/rake_helper_spec.rb +0 -656
- data/spec/chewy/repository_spec.rb +0 -50
- data/spec/chewy/rspec/build_query_spec.rb +0 -34
- data/spec/chewy/rspec/helpers_spec.rb +0 -61
- data/spec/chewy/rspec/update_index_spec.rb +0 -313
- data/spec/chewy/runtime/version_spec.rb +0 -48
- data/spec/chewy/runtime_spec.rb +0 -9
- data/spec/chewy/search/loader_spec.rb +0 -83
- data/spec/chewy/search/pagination/kaminari_examples.rb +0 -69
- data/spec/chewy/search/pagination/kaminari_spec.rb +0 -21
- data/spec/chewy/search/parameters/aggs_spec.rb +0 -5
- data/spec/chewy/search/parameters/bool_storage_examples.rb +0 -53
- data/spec/chewy/search/parameters/collapse_spec.rb +0 -5
- data/spec/chewy/search/parameters/docvalue_fields_spec.rb +0 -5
- data/spec/chewy/search/parameters/explain_spec.rb +0 -5
- data/spec/chewy/search/parameters/filter_spec.rb +0 -5
- data/spec/chewy/search/parameters/hash_storage_examples.rb +0 -59
- data/spec/chewy/search/parameters/highlight_spec.rb +0 -5
- data/spec/chewy/search/parameters/ignore_unavailable_spec.rb +0 -67
- data/spec/chewy/search/parameters/indices_spec.rb +0 -99
- data/spec/chewy/search/parameters/integer_storage_examples.rb +0 -32
- data/spec/chewy/search/parameters/knn_spec.rb +0 -5
- data/spec/chewy/search/parameters/limit_spec.rb +0 -5
- data/spec/chewy/search/parameters/load_spec.rb +0 -60
- data/spec/chewy/search/parameters/min_score_spec.rb +0 -32
- data/spec/chewy/search/parameters/none_spec.rb +0 -5
- data/spec/chewy/search/parameters/offset_spec.rb +0 -5
- data/spec/chewy/search/parameters/order_spec.rb +0 -72
- data/spec/chewy/search/parameters/post_filter_spec.rb +0 -5
- data/spec/chewy/search/parameters/preference_spec.rb +0 -5
- data/spec/chewy/search/parameters/profile_spec.rb +0 -5
- data/spec/chewy/search/parameters/query_spec.rb +0 -5
- data/spec/chewy/search/parameters/query_storage_examples.rb +0 -434
- data/spec/chewy/search/parameters/request_cache_spec.rb +0 -67
- data/spec/chewy/search/parameters/rescore_spec.rb +0 -62
- data/spec/chewy/search/parameters/script_fields_spec.rb +0 -5
- data/spec/chewy/search/parameters/search_after_spec.rb +0 -35
- data/spec/chewy/search/parameters/search_type_spec.rb +0 -5
- data/spec/chewy/search/parameters/source_spec.rb +0 -162
- data/spec/chewy/search/parameters/storage_spec.rb +0 -60
- data/spec/chewy/search/parameters/stored_fields_spec.rb +0 -126
- data/spec/chewy/search/parameters/string_array_storage_examples.rb +0 -63
- data/spec/chewy/search/parameters/string_storage_examples.rb +0 -32
- data/spec/chewy/search/parameters/suggest_spec.rb +0 -5
- data/spec/chewy/search/parameters/terminate_after_spec.rb +0 -5
- data/spec/chewy/search/parameters/timeout_spec.rb +0 -5
- data/spec/chewy/search/parameters/track_scores_spec.rb +0 -5
- data/spec/chewy/search/parameters/track_total_hits_spec.rb +0 -5
- data/spec/chewy/search/parameters/version_spec.rb +0 -5
- data/spec/chewy/search/parameters_spec.rb +0 -161
- data/spec/chewy/search/query_proxy_spec.rb +0 -95
- data/spec/chewy/search/request_spec.rb +0 -886
- data/spec/chewy/search/response_spec.rb +0 -180
- data/spec/chewy/search/scrolling_spec.rb +0 -171
- data/spec/chewy/search_spec.rb +0 -127
- data/spec/chewy/stash_spec.rb +0 -85
- data/spec/chewy/strategy/active_job_spec.rb +0 -73
- data/spec/chewy/strategy/atomic_no_refresh_spec.rb +0 -60
- data/spec/chewy/strategy/atomic_spec.rb +0 -61
- data/spec/chewy/strategy/delayed_sidekiq_spec.rb +0 -225
- data/spec/chewy/strategy/lazy_sidekiq_spec.rb +0 -214
- data/spec/chewy/strategy/sidekiq_spec.rb +0 -52
- data/spec/chewy/strategy_spec.rb +0 -125
- data/spec/chewy_spec.rb +0 -100
- data/spec/spec_helper.rb +0 -69
- data/spec/support/active_record.rb +0 -124
- data/spec/support/class_helpers.rb +0 -16
- data/spec/support/fail_helpers.rb +0 -13
data/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# The Chewy Community Code of Conduct
|
|
2
|
-
|
|
3
|
-
**Note:** We have picked the following code of conduct based on [Ruby's own code of conduct](https://www.ruby-lang.org/en/conduct/).
|
|
4
|
-
|
|
5
|
-
This document provides a few simple community guidelines for a safe, respectful,
|
|
6
|
-
productive, and collaborative place for any person who is willing to contribute
|
|
7
|
-
to the Chewy community. It applies to all "collaborative spaces", which are
|
|
8
|
-
defined as community communications channels (such as mailing lists, submitted
|
|
9
|
-
patches, commit comments, etc.).
|
|
10
|
-
|
|
11
|
-
* Participants will be tolerant of opposing views.
|
|
12
|
-
* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
|
|
13
|
-
* When interpreting the words and actions of others, participants should always assume good intentions.
|
|
14
|
-
* Behaviour which can be reasonably considered harassment will not be tolerated.
|
data/CONTRIBUTING.md
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# Contributing
|
|
2
|
-
|
|
3
|
-
If you discover issues, have ideas for improvements or new features,
|
|
4
|
-
please report them to the [issue tracker][1] of the repository or
|
|
5
|
-
submit a pull request. Please, try to follow these guidelines when you
|
|
6
|
-
do so.
|
|
7
|
-
|
|
8
|
-
## Issue reporting
|
|
9
|
-
|
|
10
|
-
* Check that the issue has not already been reported.
|
|
11
|
-
* Check that the issue has not already been fixed in the latest code
|
|
12
|
-
(a.k.a. `master`).
|
|
13
|
-
* Be clear, concise and precise in your description of the problem.
|
|
14
|
-
* Open an issue with a descriptive title and a summary in grammatically correct,
|
|
15
|
-
complete sentences.
|
|
16
|
-
* Include the versions of Chewy, Elasticsearch, Ruby, Rails, etc.
|
|
17
|
-
* Include any relevant code to the issue summary.
|
|
18
|
-
|
|
19
|
-
## Pull requests
|
|
20
|
-
|
|
21
|
-
* Read [how to properly contribute to open source projects on GitHub][2].
|
|
22
|
-
* Fork the project.
|
|
23
|
-
* Use a topic/feature branch to easily amend a pull request later, if necessary.
|
|
24
|
-
* Write [good commit messages][3].
|
|
25
|
-
* Use the same coding conventions as the rest of the project.
|
|
26
|
-
* Commit and push until you are happy with your contribution.
|
|
27
|
-
* If your change has a corresponding open GitHub issue, prefix the commit message with `[Fix #github-issue-number]`.
|
|
28
|
-
* Make sure to add tests for it. This is important so I don't break it
|
|
29
|
-
in a future version unintentionally.
|
|
30
|
-
* Add an entry to the [Changelog](CHANGELOG.md).
|
|
31
|
-
* Please try not to mess with the Rakefile, version, or history. If
|
|
32
|
-
you want to have your own version, or is otherwise necessary, that
|
|
33
|
-
is fine, but please isolate to its own commit so I can cherry-pick
|
|
34
|
-
around it.
|
|
35
|
-
* Make sure the test suite is passing and the code you wrote doesn't produce
|
|
36
|
-
RuboCop offenses.
|
|
37
|
-
* [Squash related commits together][5].
|
|
38
|
-
* Open a [pull request][4] that relates to *only* one subject with a clear title
|
|
39
|
-
and description in grammatically correct, complete sentences.
|
|
40
|
-
|
|
41
|
-
## Changelog entry format
|
|
42
|
-
|
|
43
|
-
Here are a few examples:
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
* [#753](https://github.com/toptal/chewy/pull/753): Add support for direct_import parameter to skip objects reloading. ([@TikiTDO][], [@dalthon][])
|
|
47
|
-
* [#739](https://github.com/toptal/chewy/pull/739): Remove explicit `main` branch dependencies on `rspec-*` gems after `rspec-mocks` 3.10.2 is released. ([@rabotyaga][])
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
* Mark it up in [Markdown syntax][6].
|
|
51
|
-
* The entry line should start with `* ` (an asterisk and a space).
|
|
52
|
-
* If the change has a related GitHub issue (e.g. a bug fix for a reported issue), put a link to the issue as `[#123](https://github.com/toptal/chewy/issues/123): `.
|
|
53
|
-
* Describe the change briefly. The sentence should end with a punctuation.
|
|
54
|
-
* If this is a breaking change, mark it with `**(Breaking)**`.
|
|
55
|
-
* At the end of the entry, add an implicit link to your GitHub user page as `([@username][])`.
|
|
56
|
-
* If this is your first contribution to the project, add a link definition for the implicit link to the bottom of the changelog as `[@username]: https://github.com/username`.
|
|
57
|
-
|
|
58
|
-
[1]: https://github.com/toptal/chewy/issues
|
|
59
|
-
[2]: https://www.gun.io/blog/how-to-github-fork-branch-and-pull-request
|
|
60
|
-
[3]: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
|
61
|
-
[4]: https://help.github.com/articles/about-pull-requests
|
|
62
|
-
[5]: http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html
|
|
63
|
-
[6]: https://daringfireball.net/projects/markdown/syntax
|
data/Gemfile
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
gem 'activerecord'
|
|
4
|
-
|
|
5
|
-
gem 'activejob', require: false
|
|
6
|
-
gem 'sidekiq', require: false
|
|
7
|
-
|
|
8
|
-
gem 'kaminari-core', require: false
|
|
9
|
-
|
|
10
|
-
gem 'parallel', require: false
|
|
11
|
-
gem 'ruby-progressbar', require: false
|
|
12
|
-
|
|
13
|
-
gem 'guard'
|
|
14
|
-
gem 'guard-rspec'
|
|
15
|
-
|
|
16
|
-
gem 'redcarpet'
|
|
17
|
-
gem 'yard'
|
|
18
|
-
|
|
19
|
-
gem 'rexml'
|
|
20
|
-
|
|
21
|
-
eval_gemfile 'gemfiles/base.gemfile'
|
|
22
|
-
gemspec
|
data/Guardfile
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# A sample Guardfile
|
|
2
|
-
# More info at https://github.com/guard/guard#readme
|
|
3
|
-
|
|
4
|
-
guard :rspec, cmd: 'rspec' do
|
|
5
|
-
watch(%r{^spec/.+_spec\.rb$})
|
|
6
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
7
|
-
watch('spec/spec_helper.rb') { 'spec' }
|
|
8
|
-
|
|
9
|
-
# Rails example
|
|
10
|
-
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
|
11
|
-
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
|
12
|
-
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) do |m|
|
|
13
|
-
["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"]
|
|
14
|
-
end
|
|
15
|
-
watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
|
|
16
|
-
watch('config/routes.rb') { 'spec/routing' }
|
|
17
|
-
watch('app/controllers/application_controller.rb') { 'spec/controllers' }
|
|
18
|
-
|
|
19
|
-
# Capybara features specs
|
|
20
|
-
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
|
21
|
-
|
|
22
|
-
# Turnip features and steps
|
|
23
|
-
watch(%r{^spec/acceptance/(.+)\.feature$})
|
|
24
|
-
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
|
25
|
-
end
|
data/Rakefile
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
require 'bundler/gem_tasks'
|
|
2
|
-
require 'rspec/core/rake_task'
|
|
3
|
-
require 'elasticsearch/extensions/test/cluster/tasks'
|
|
4
|
-
|
|
5
|
-
RSpec::Core::RakeTask.new(:spec)
|
|
6
|
-
|
|
7
|
-
task default: :spec
|
|
8
|
-
|
|
9
|
-
namespace :es do
|
|
10
|
-
task :start do
|
|
11
|
-
Rake.application['elasticsearch:start'].invoke
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
task :stop do
|
|
15
|
-
Rake.application['elasticsearch:stop'].invoke
|
|
16
|
-
end
|
|
17
|
-
end
|
data/chewy.gemspec
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
lib = File.expand_path('lib', __dir__)
|
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
-
require 'chewy/version'
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name = 'chewy'
|
|
7
|
-
spec.version = Chewy::VERSION
|
|
8
|
-
spec.authors = ['Toptal, LLC', 'pyromaniac']
|
|
9
|
-
spec.email = ['open-source@toptal.com', 'kinwizard@gmail.com']
|
|
10
|
-
spec.summary = 'Elasticsearch ODM client wrapper'
|
|
11
|
-
spec.description = 'Chewy provides functionality for Elasticsearch index handling, documents import mappings and chainable query DSL'
|
|
12
|
-
spec.homepage = 'https://github.com/toptal/chewy'
|
|
13
|
-
spec.license = 'MIT'
|
|
14
|
-
spec.required_ruby_version = '~> 3.2'
|
|
15
|
-
|
|
16
|
-
spec.files = `git ls-files`.split($RS)
|
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
-
spec.require_paths = ['lib']
|
|
19
|
-
|
|
20
|
-
spec.add_dependency 'activesupport', '>= 7.2'
|
|
21
|
-
spec.add_dependency 'elasticsearch', '>= 8.14', '< 9.0'
|
|
22
|
-
spec.add_dependency 'elasticsearch-dsl'
|
|
23
|
-
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
24
|
-
end
|
data/docker-compose.yml
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
elasticsearch_test:
|
|
3
|
-
image: "elasticsearch:8.15.0"
|
|
4
|
-
environment:
|
|
5
|
-
- bootstrap.memory_lock=${ES_MEMORY_LOCK:-false}
|
|
6
|
-
- "ES_JAVA_OPTS=-Xms${TEST_ES_HEAP_SIZE:-500m} -Xmx${TEST_ES_HEAP_SIZE:-500m}"
|
|
7
|
-
- discovery.type=single-node
|
|
8
|
-
- xpack.security.enabled=false
|
|
9
|
-
ports:
|
|
10
|
-
- "127.0.0.1:9250:9200"
|
|
11
|
-
ulimits:
|
|
12
|
-
nofile:
|
|
13
|
-
soft: 65536
|
|
14
|
-
hard: 65536
|
data/docs/README.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Chewy Documentation
|
|
2
|
-
|
|
3
|
-
Getting started — see the main [README](../README.md).
|
|
4
|
-
|
|
5
|
-
## Reference
|
|
6
|
-
|
|
7
|
-
- [Configuration](configuration.md) — client settings, update strategies, notifications, integrations
|
|
8
|
-
- [Indexing](indexing.md) — index definition, field types, crutches, witchcraft, index manipulation
|
|
9
|
-
- [Import](import.md) — import options, raw import, journaling
|
|
10
|
-
- [Querying](querying.md) — search requests, pagination, scopes, scroll, loading
|
|
11
|
-
|
|
12
|
-
## Operations
|
|
13
|
-
|
|
14
|
-
- [Rake Tasks](rake_tasks.md) — reindexing, syncing, journal management, parallelization
|
|
15
|
-
- [Testing](testing.md) — RSpec, Minitest, DatabaseCleaner
|
|
16
|
-
- [Troubleshooting](troubleshooting.md) — common errors, debugging imports, ES 8 gotchas
|
data/docs/configuration.md
DELETED
|
@@ -1,440 +0,0 @@
|
|
|
1
|
-
# Configuration
|
|
2
|
-
|
|
3
|
-
## Client settings
|
|
4
|
-
|
|
5
|
-
To configure the Chewy client you need to add `chewy.rb` file with `Chewy.settings` hash:
|
|
6
|
-
|
|
7
|
-
```ruby
|
|
8
|
-
# config/initializers/chewy.rb
|
|
9
|
-
Chewy.settings = {host: 'localhost:9250'} # do not use environments
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
And add `chewy.yml` configuration file.
|
|
13
|
-
|
|
14
|
-
You can create `chewy.yml` manually or run `rails g chewy:install` to generate it:
|
|
15
|
-
|
|
16
|
-
```yaml
|
|
17
|
-
# config/chewy.yml
|
|
18
|
-
# separate environment configs
|
|
19
|
-
test:
|
|
20
|
-
host: 'localhost:9250'
|
|
21
|
-
prefix: 'test'
|
|
22
|
-
development:
|
|
23
|
-
host: 'localhost:9200'
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
The resulting config merges both hashes. Client options are passed as is to `Elasticsearch::Transport::Client` except for the `:prefix`, which is used internally by Chewy to create prefixed index names:
|
|
27
|
-
|
|
28
|
-
```ruby
|
|
29
|
-
Chewy.settings = {prefix: 'test'}
|
|
30
|
-
UsersIndex.index_name # => 'test_users'
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
The logger may be set explicitly:
|
|
34
|
-
|
|
35
|
-
```ruby
|
|
36
|
-
Chewy.logger = Logger.new(STDOUT)
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
See [config.rb](../lib/chewy/config.rb) for more details.
|
|
40
|
-
|
|
41
|
-
### AWS Elasticsearch
|
|
42
|
-
|
|
43
|
-
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`.
|
|
44
|
-
You'll need an additional gem for Faraday middleware: add `gem 'faraday_middleware-aws-sigv4'` to your Gemfile.
|
|
45
|
-
|
|
46
|
-
```ruby
|
|
47
|
-
require 'faraday_middleware/aws_sigv4'
|
|
48
|
-
|
|
49
|
-
Chewy.settings = {
|
|
50
|
-
host: 'http://my-es-instance-on-aws.us-east-1.es.amazonaws.com:80',
|
|
51
|
-
port: 80, # 443 for https host
|
|
52
|
-
transport_options: {
|
|
53
|
-
headers: { content_type: 'application/json' },
|
|
54
|
-
proc: -> (f) do
|
|
55
|
-
f.request :aws_sigv4,
|
|
56
|
-
service: 'es',
|
|
57
|
-
region: 'us-east-1',
|
|
58
|
-
access_key_id: ENV['AWS_ACCESS_KEY'],
|
|
59
|
-
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
|
|
60
|
-
end
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Elasticsearch client options
|
|
66
|
-
|
|
67
|
-
All connection options, except the `:prefix`, are passed to the `Elasticseach::Client.new` ([chewy/lib/chewy.rb](https://github.com/toptal/chewy/blob/f5bad9f83c21416ac10590f6f34009c645062e89/lib/chewy.rb#L153-L160)):
|
|
68
|
-
|
|
69
|
-
Here's the relevant Elasticsearch documentation on the subject: https://rubydoc.info/gems/elasticsearch-transport#setting-hosts
|
|
70
|
-
|
|
71
|
-
## Index update strategies
|
|
72
|
-
|
|
73
|
-
Assume you've got the following code (see [indexing.md](indexing.md#index-definition) for the full `update_index` DSL):
|
|
74
|
-
|
|
75
|
-
```ruby
|
|
76
|
-
class City < ActiveRecord::Base
|
|
77
|
-
update_index 'cities', :self
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
class CitiesIndex < Chewy::Index
|
|
81
|
-
index_scope City
|
|
82
|
-
field :name
|
|
83
|
-
end
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
If you do something like `City.first.save!` you'll get an UndefinedUpdateStrategy exception instead of the object saving and index updating. This exception forces you to choose an appropriate update strategy for the current context.
|
|
87
|
-
|
|
88
|
-
If you want to return to the pre-0.7.0 behavior - just set `Chewy.root_strategy = :bypass`.
|
|
89
|
-
|
|
90
|
-
### `:atomic`
|
|
91
|
-
|
|
92
|
-
The main strategy here is `:atomic`. Assume you have to update a lot of records in the db.
|
|
93
|
-
|
|
94
|
-
```ruby
|
|
95
|
-
Chewy.strategy(:atomic) do
|
|
96
|
-
City.popular.map(&:do_some_update_action!)
|
|
97
|
-
end
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Using this strategy delays the index update request until the end of the block. Updated records are aggregated and the index update happens with the bulk API. So this strategy is highly optimized.
|
|
101
|
-
|
|
102
|
-
### `:sidekiq`
|
|
103
|
-
|
|
104
|
-
This does the same thing as `:atomic`, but asynchronously using sidekiq. Patch `Chewy::Strategy::Sidekiq::Worker` for index updates improving.
|
|
105
|
-
|
|
106
|
-
```ruby
|
|
107
|
-
Chewy.strategy(:sidekiq) do
|
|
108
|
-
City.popular.map(&:do_some_update_action!)
|
|
109
|
-
end
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
The default queue name is `chewy`, you can customize it in settings: `sidekiq.queue_name`
|
|
113
|
-
```
|
|
114
|
-
Chewy.settings[:sidekiq] = {queue: :low}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### `:lazy_sidekiq`
|
|
118
|
-
|
|
119
|
-
This does the same thing as `:sidekiq`, but with lazy evaluation. Beware it does not allow you to use any non-persistent record state for indices and conditions because record will be re-fetched from database asynchronously using sidekiq. However for destroying records strategy will fallback to `:sidekiq` because it's not possible to re-fetch deleted records from database.
|
|
120
|
-
|
|
121
|
-
The purpose of this strategy is to improve the response time of the code that should update indexes, as it does not only defer actual ES calls to a background job but `update_index` callbacks evaluation (for created and updated objects) too. Similar to `:sidekiq`, index update is asynchronous so this strategy cannot be used when data and index synchronization is required.
|
|
122
|
-
|
|
123
|
-
```ruby
|
|
124
|
-
Chewy.strategy(:lazy_sidekiq) do
|
|
125
|
-
City.popular.map(&:do_some_update_action!)
|
|
126
|
-
end
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
The default queue name is `chewy`, you can customize it in settings: `sidekiq.queue_name`
|
|
130
|
-
```
|
|
131
|
-
Chewy.settings[:sidekiq] = {queue: :low}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### `:delayed_sidekiq`
|
|
135
|
-
|
|
136
|
-
It accumulates IDs of records to be reindexed during the latency window in Redis and then performs the reindexing of all accumulated records at once.
|
|
137
|
-
This strategy is very useful in the case of frequently mutated records.
|
|
138
|
-
It supports the `update_fields` option, so it will attempt to select just enough data from the database.
|
|
139
|
-
|
|
140
|
-
Keep in mind, this strategy does not guarantee reindexing in the event of Sidekiq worker termination or an error during the reindexing phase.
|
|
141
|
-
This behavior is intentional to prevent continuous growth of Redis db.
|
|
142
|
-
|
|
143
|
-
There are three options that can be defined in the index:
|
|
144
|
-
```ruby
|
|
145
|
-
class CitiesIndex...
|
|
146
|
-
strategy_config delayed_sidekiq: {
|
|
147
|
-
latency: 3,
|
|
148
|
-
margin: 2,
|
|
149
|
-
ttl: 60 * 60 * 24,
|
|
150
|
-
reindex_wrapper: ->(&reindex) {
|
|
151
|
-
ActiveRecord::Base.connected_to(role: :reading) { reindex.call }
|
|
152
|
-
}
|
|
153
|
-
# latency - will prevent scheduling identical jobs
|
|
154
|
-
# margin - main purpose is to cover db replication lag by the margin
|
|
155
|
-
# ttl - a chunk expiration time (in seconds)
|
|
156
|
-
# reindex_wrapper - lambda that accepts block to wrap that reindex process AR connection block.
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
...
|
|
160
|
-
end
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Also you can define defaults in the `initializers/chewy.rb`
|
|
164
|
-
```ruby
|
|
165
|
-
Chewy.settings = {
|
|
166
|
-
strategy_config: {
|
|
167
|
-
delayed_sidekiq: {
|
|
168
|
-
latency: 3,
|
|
169
|
-
margin: 2,
|
|
170
|
-
ttl: 60 * 60 * 24,
|
|
171
|
-
reindex_wrapper: ->(&reindex) {
|
|
172
|
-
ActiveRecord::Base.connected_to(role: :reading) { reindex.call }
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
```
|
|
179
|
-
or in `config/chewy.yml`
|
|
180
|
-
```ruby
|
|
181
|
-
strategy_config:
|
|
182
|
-
delayed_sidekiq:
|
|
183
|
-
latency: 3
|
|
184
|
-
margin: 2
|
|
185
|
-
ttl: <%= 60 * 60 * 24 %>
|
|
186
|
-
# reindex_wrapper setting is not possible here!!! use the initializer instead
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
You can use the strategy identically to other strategies
|
|
190
|
-
```ruby
|
|
191
|
-
Chewy.strategy(:delayed_sidekiq) do
|
|
192
|
-
City.popular.map(&:do_some_update_action!)
|
|
193
|
-
end
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
The default queue name is `chewy`, you can customize it in settings: `sidekiq.queue_name`
|
|
197
|
-
```
|
|
198
|
-
Chewy.settings[:sidekiq] = {queue: :low}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
Explicit call of the reindex using `:delayed_sidekiq strategy`
|
|
202
|
-
```ruby
|
|
203
|
-
CitiesIndex.import([1, 2, 3], strategy: :delayed_sidekiq)
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Explicit call of the reindex using `:delayed_sidekiq` strategy with `:update_fields` support
|
|
207
|
-
```ruby
|
|
208
|
-
CitiesIndex.import([1, 2, 3], update_fields: [:name], strategy: :delayed_sidekiq)
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
While running tests with delayed_sidekiq strategy and Sidekiq is using a real redis instance that is NOT cleaned up in between tests (via e.g. `Sidekiq.redis(&:flushdb)`), you'll want to cleanup some redis keys in between tests to avoid state leaking and flaky tests. Chewy provides a convenience method for that:
|
|
212
|
-
```ruby
|
|
213
|
-
# it might be a good idea to also add to your testing setup, e.g.: a rspec `before` hook
|
|
214
|
-
Chewy::Strategy::DelayedSidekiq.clear_timechunks!
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### `:active_job`
|
|
218
|
-
|
|
219
|
-
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.
|
|
220
|
-
|
|
221
|
-
```ruby
|
|
222
|
-
Chewy.strategy(:active_job) do
|
|
223
|
-
City.popular.map(&:do_some_update_action!)
|
|
224
|
-
end
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
The default queue name is `chewy`, you can customize it in settings: `active_job.queue_name`
|
|
228
|
-
```
|
|
229
|
-
Chewy.settings[:active_job] = {queue: :low}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### `:urgent`
|
|
233
|
-
|
|
234
|
-
The following strategy is convenient if you are going to update documents in your index one by one.
|
|
235
|
-
|
|
236
|
-
```ruby
|
|
237
|
-
Chewy.strategy(:urgent) do
|
|
238
|
-
City.popular.map(&:do_some_update_action!)
|
|
239
|
-
end
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
This code will perform `City.popular.count` requests for ES documents update.
|
|
243
|
-
|
|
244
|
-
It is convenient for use in e.g. the Rails console with non-block notation:
|
|
245
|
-
|
|
246
|
-
```ruby
|
|
247
|
-
> Chewy.strategy(:urgent)
|
|
248
|
-
> City.popular.map(&:do_some_update_action!)
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### `:bypass`
|
|
252
|
-
|
|
253
|
-
When the bypass strategy is active the index will not be automatically updated on object save.
|
|
254
|
-
|
|
255
|
-
For example, on `City.first.save!` the cities index would not be updated.
|
|
256
|
-
|
|
257
|
-
### Nesting
|
|
258
|
-
|
|
259
|
-
Strategies are designed to allow nesting, so it is possible to redefine it for nested contexts.
|
|
260
|
-
|
|
261
|
-
```ruby
|
|
262
|
-
Chewy.strategy(:atomic) do
|
|
263
|
-
city1.do_update!
|
|
264
|
-
Chewy.strategy(:urgent) do
|
|
265
|
-
city2.do_update!
|
|
266
|
-
city3.do_update!
|
|
267
|
-
# there will be 2 update index requests for city2 and city3
|
|
268
|
-
end
|
|
269
|
-
city4.do_update!
|
|
270
|
-
# city1 and city4 will be grouped in one index update request
|
|
271
|
-
end
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Non-block notation
|
|
275
|
-
|
|
276
|
-
It is possible to nest strategies without blocks:
|
|
277
|
-
|
|
278
|
-
```ruby
|
|
279
|
-
Chewy.strategy(:urgent)
|
|
280
|
-
city1.do_update! # index updated
|
|
281
|
-
Chewy.strategy(:bypass)
|
|
282
|
-
city2.do_update! # update bypassed
|
|
283
|
-
Chewy.strategy.pop
|
|
284
|
-
city3.do_update! # index updated again
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Designing your own strategies
|
|
288
|
-
|
|
289
|
-
See [strategy/base.rb](../lib/chewy/strategy/base.rb) for more details. See [strategy/atomic.rb](../lib/chewy/strategy/atomic.rb) for an example.
|
|
290
|
-
|
|
291
|
-
## Rails application strategies integration
|
|
292
|
-
|
|
293
|
-
There are a couple of predefined strategies for your Rails application. Initially, the Rails console uses the `:urgent` strategy by default, except in the sandbox case. When you are running sandbox it switches to the `:bypass` strategy to avoid polluting the index.
|
|
294
|
-
|
|
295
|
-
Migrations are wrapped with the `:bypass` strategy. Because the main behavior implies that indices are reset after migration, there is no need for extra index updates. Also indexing might be broken during migrations because of the outdated schema.
|
|
296
|
-
|
|
297
|
-
Controller actions are wrapped with the configurable value of `Chewy.request_strategy` and defaults to `:atomic`. This is done at the middleware level to reduce the number of index update requests inside actions.
|
|
298
|
-
|
|
299
|
-
It is also a good idea to set up the `:bypass` strategy inside your test suite and import objects manually only when needed, and use `Chewy.massacre` when needed to flush test ES indices before every example. This will allow you to minimize unnecessary ES requests and reduce overhead.
|
|
300
|
-
|
|
301
|
-
Deprecation note: since version 8 wildcard removing of indices is disabled by default. You can enable it for a cluster with setting `action.destructive_requires_name` to false.
|
|
302
|
-
|
|
303
|
-
```ruby
|
|
304
|
-
RSpec.configure do |config|
|
|
305
|
-
config.before(:suite) do
|
|
306
|
-
Chewy.strategy(:bypass)
|
|
307
|
-
end
|
|
308
|
-
end
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
See [testing.md](testing.md) for more on RSpec/Minitest integration and the DatabaseCleaner caveat.
|
|
312
|
-
|
|
313
|
-
## `ActiveSupport::Notifications` support
|
|
314
|
-
|
|
315
|
-
Chewy has notifying the following events:
|
|
316
|
-
|
|
317
|
-
### `search_query.chewy` payload
|
|
318
|
-
|
|
319
|
-
* `payload[:index]`: requested index class
|
|
320
|
-
* `payload[:request]`: request hash
|
|
321
|
-
|
|
322
|
-
### `import_objects.chewy` payload
|
|
323
|
-
|
|
324
|
-
* `payload[:index]`: currently imported index name
|
|
325
|
-
* `payload[:import]`: imports stats, total imported and deleted objects count:
|
|
326
|
-
|
|
327
|
-
```ruby
|
|
328
|
-
{index: 30, delete: 5}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
* `payload[:errors]`: might not exist. Contains grouped errors with objects ids list:
|
|
332
|
-
|
|
333
|
-
```ruby
|
|
334
|
-
{index: {
|
|
335
|
-
'error 1 text' => ['1', '2', '3'],
|
|
336
|
-
'error 2 text' => ['4']
|
|
337
|
-
}, delete: {
|
|
338
|
-
'delete error text' => ['10', '12']
|
|
339
|
-
}}
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
## NewRelic integration
|
|
343
|
-
|
|
344
|
-
**Note:** this example was written for an older version of the NewRelic APM agent and may need adaptation for current versions. The general pattern of subscribing to Chewy's `ActiveSupport::Notifications` events remains valid.
|
|
345
|
-
|
|
346
|
-
To integrate with NewRelic you may use the following example source (config/initializers/chewy.rb):
|
|
347
|
-
|
|
348
|
-
```ruby
|
|
349
|
-
require 'new_relic/agent/instrumentation/evented_subscriber'
|
|
350
|
-
|
|
351
|
-
class ChewySubscriber < NewRelic::Agent::Instrumentation::EventedSubscriber
|
|
352
|
-
def start(name, id, payload)
|
|
353
|
-
event = ChewyEvent.new(name, Time.current, nil, id, payload)
|
|
354
|
-
push_event(event)
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
def finish(_name, id, _payload)
|
|
358
|
-
pop_event(id).finish
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
class ChewyEvent < NewRelic::Agent::Instrumentation::Event
|
|
362
|
-
OPERATIONS = {
|
|
363
|
-
'import_objects.chewy' => 'import',
|
|
364
|
-
'search_query.chewy' => 'search',
|
|
365
|
-
'delete_query.chewy' => 'delete'
|
|
366
|
-
}.freeze
|
|
367
|
-
|
|
368
|
-
def initialize(*args)
|
|
369
|
-
super
|
|
370
|
-
@segment = start_segment
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
def start_segment
|
|
374
|
-
segment = NewRelic::Agent::Transaction::DatastoreSegment.new product, operation, collection, host, port
|
|
375
|
-
if (txn = state.current_transaction)
|
|
376
|
-
segment.transaction = txn
|
|
377
|
-
end
|
|
378
|
-
segment.notice_sql @payload[:request].to_s
|
|
379
|
-
segment.start
|
|
380
|
-
segment
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def finish
|
|
384
|
-
if (txn = state.current_transaction)
|
|
385
|
-
txn.add_segment @segment
|
|
386
|
-
end
|
|
387
|
-
@segment.finish
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
private
|
|
391
|
-
|
|
392
|
-
def state
|
|
393
|
-
@state ||= NewRelic::Agent::TransactionState.tl_get
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
def product
|
|
397
|
-
'Elasticsearch'
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def operation
|
|
401
|
-
OPERATIONS[name]
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
def collection
|
|
405
|
-
payload.values_at(:type, :index)
|
|
406
|
-
.reject { |value| value.try(:empty?) }
|
|
407
|
-
.first
|
|
408
|
-
.to_s
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
def host
|
|
412
|
-
Chewy.client.transport.hosts.first[:host]
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
def port
|
|
416
|
-
Chewy.client.transport.hosts.first[:port]
|
|
417
|
-
end
|
|
418
|
-
end
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
ActiveSupport::Notifications.subscribe(/.chewy$/, ChewySubscriber.new)
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
## Import scope clean-up behavior
|
|
425
|
-
|
|
426
|
-
Whenever you set the `import_scope` for the index, in the case of ActiveRecord,
|
|
427
|
-
options for order, offset and limit will be removed. You can set the behavior of
|
|
428
|
-
chewy, before the clean-up itself.
|
|
429
|
-
|
|
430
|
-
The default behavior is a warning sent to the Chewy logger (`:warn`). Another more
|
|
431
|
-
restrictive option is raising an exception (`:raise`). Both options have a
|
|
432
|
-
negative impact on performance since verifying whether the code uses any of
|
|
433
|
-
these options requires building AREL query.
|
|
434
|
-
|
|
435
|
-
To avoid the loading time impact, you can ignore the check (`:ignore`) before
|
|
436
|
-
the clean-up.
|
|
437
|
-
|
|
438
|
-
```
|
|
439
|
-
Chewy.import_scope_cleanup_behavior = :ignore
|
|
440
|
-
```
|