### Chewy Configuration Example (chewy.yml) Source: https://github.com/toptal/chewy/blob/master/README.md Example of environment-specific configurations for Chewy, including host and prefix settings. ```yaml # config/chewy.yml test: host: 'localhost:9250' prefix: 'test' development: host: 'localhost:9200' ``` -------------------------------- ### Chewy YAML Configuration Example Source: https://github.com/toptal/chewy/blob/master/README.md This YAML snippet shows a typical `chewy.yml` configuration file. It defines host and prefix settings for different environments like 'test' and 'development'. This file can be generated using `rails g chewy:install`. ```yaml # config/chewy.yml # separate environment configs test: host: 'localhost:9250' prefix: 'test' development: host: 'localhost:9200' ``` -------------------------------- ### Changelog Entry Examples (Markdown) Source: https://github.com/toptal/chewy/blob/master/CONTRIBUTING.md Examples of changelog entries formatted in Markdown, demonstrating how to link to issues, describe changes, and attribute contributors. These entries follow a specific structure for consistency. ```markdown * [#753](https://github.com/toptal/chewy/pull/753): Add support for direct_import parameter to skip objects reloading. ([@TikiTDO][], [@dalthon][]) * [#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][]) ``` -------------------------------- ### Configure Chewy Client Settings Source: https://github.com/toptal/chewy/blob/master/README.md Example of how to set the Elasticsearch host for Chewy in a Rails initializer file. ```ruby Chewy.settings = {host: 'localhost:9250'} ``` -------------------------------- ### Configure Chewy with Security Enabled Source: https://github.com/toptal/chewy/blob/master/README.md Example of chewy.yml configuration when Elasticsearch security is enabled, including user, password, and CA certificate path. ```yaml # config/chewy.yml development: host: 'localhost:9200' user: 'elastic' password: 'SomeLongPassword' transport_options: ssl: ca_file: './tmp/http_ca.crt' ``` -------------------------------- ### Install Chewy Gem Source: https://github.com/toptal/chewy/blob/master/README.md Instructions for adding the Chewy gem to your Ruby on Rails application's Gemfile and executing the bundle command for installation. ```ruby gem 'chewy' $ bundle $ gem install chewy ``` -------------------------------- ### Indexing with Associations in Ruby (Chewy) Source: https://github.com/toptal/chewy/blob/master/README.md An example of indexing product data in Ruby using Chewy, including fetching associated category names. It shows a standard approach using `includes` and `map`. ```ruby class ProductsIndex < Chewy::Index index_scope Product.includes(:categories) field :name field :category_names, value: ->(product) { product.categories.map(&:name) } # or shorter just -> { categories.map(&:name) } end ``` -------------------------------- ### Indexing Flow with Crutches in Ruby (Chewy) Source: https://github.com/toptal/chewy/blob/master/README.md An example of the indexing flow in Ruby when using Chewy's Crutches technology. It shows how to pre-fetch crutch data and then use it when building the bulk body. ```ruby Product.includes(:categories).find_in_batches(1000) do |batch| crutches[:categories] = ProductCategory.joins(:category).where(product_id: batch.map(&:id)).pluck(:product_id, 'categories.name') .each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) } bulk_body = batch.map do |object| {name: object.name, category_names: crutches[:categories][object.id]}.to_json end Chewy.client.bulk bulk_body end ``` -------------------------------- ### Configure Chewy Client Connection and Strategies in Ruby Source: https://context7.com/toptal/chewy/llms.txt This code configures the Chewy client's connection details, logging, and update strategies. It shows standard configuration and an example for connecting to AWS Elasticsearch with IAM authentication using `faraday_middleware/aws_sigv4`. It also includes an example of environment-specific configurations in `config/chewy.yml`. ```ruby # config/initializers/chewy.rb Chewy.settings = { host: 'localhost:9200', transport_options: { request: { timeout: 5 }, headers: { content_type: 'application/json' } } } # Set logger Chewy.logger = Logger.new(STDOUT) # Configure update strategies Chewy.root_strategy = :bypass # Or :atomic, :urgent, :sidekiq Chewy.request_strategy = :atomic # For AWS Elasticsearch with IAM authentication require 'faraday_middleware/aws_sigv4' Chewy.settings = { host: 'https://my-es-instance.us-east-1.es.amazonaws.com', port: 443, transport_options: { headers: { content_type: 'application/json' }, proc: ->(f) do f.request :aws_sigv4, service: 'es', region: 'us-east-1', access_key_id: ENV['AWS_ACCESS_KEY'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] end } } # config/chewy.yml # Supports environment-specific configuration test: host: 'localhost:9250' prefix: 'test' development: host: 'localhost:9200' production: host: 'es-production.example.com:9200' prefix: 'prod' ``` -------------------------------- ### Create User Record and Observe Indexing - Ruby Console Source: https://github.com/toptal/chewy/blob/master/README.md This example demonstrates creating a User record via the Rails console. Upon creation, Chewy automatically updates the 'users' index, as indicated by the log output. The comment shows how to create a user with basic attributes. ```ruby User.create( first_name: "test1", last_name: "test1", email: 'test1@example.com', # other fields ) # UsersIndex Import (355.3ms) {:index=>1} # => # ``` -------------------------------- ### Chewy 7.2: Update Indexes with Simplified DSL (Ruby) Source: https://github.com/toptal/chewy/blob/master/migration_guide.md Illustrates the transition from `define_type` blocks to `index_scope` clauses in Chewy 7.2 for updating index configurations. The `index_scope` clause can be omitted if no specific scope or options like 'name' are required. ```ruby # Old syntax: define_type :city do # ... end # New syntax: index_scope :city, if: -> { some_condition } do # ... end # Or simply: index_scope ``` -------------------------------- ### Rake Tasks for Elasticsearch Cluster Control Source: https://github.com/toptal/chewy/blob/master/README.md Provides Rake tasks to start and stop a local Elasticsearch cluster for development and testing purposes. ```bash rake elasticsearch:start # start Elasticsearch cluster on 9250 port for tests rake elasticsearch:stop # stop Elasticsearch ``` -------------------------------- ### Urgent Strategy Non-Block Notation in Console Source: https://github.com/toptal/chewy/blob/master/README.md This example demonstrates using the :urgent strategy without a block, commonly used in interactive console sessions. After setting the strategy, subsequent update operations will be performed urgently. ```ruby > Chewy.strategy(:urgent) > City.popular.map(&:do_some_update_action!) ``` -------------------------------- ### Aggregations Query - Ruby Source: https://context7.com/toptal/chewy/llms.txt Execute a search query and simultaneously perform aggregations. This example counts documents by country using the `terms` aggregation. ```ruby # Aggregations UsersIndex.query(match_all: {}) .aggs(by_country: {terms: {field: 'country'}}) ``` -------------------------------- ### Non-Block Notation for Nested Strategies Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby example shows how to nest strategies without using blocks. It sequentially activates :urgent, then :bypass, and finally pops the :bypass strategy to revert to the previous one, allowing for fine-grained control over update behavior. ```ruby Chewy.strategy(:urgent) city1.do_update! # index updated Chewy.strategy(:bypass) city2.do_update! # update bypassed Chewy.strategy.pop city3.do_update! # index updated again ``` -------------------------------- ### Import with Delayed Sidekiq and Update Fields Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby example shows how to import records with the :delayed_sidekiq strategy while specifying which fields to update. This optimizes the reindexing process by only fetching and updating specified fields from the database. ```ruby CitiesIndex.import([1, 2, 3], update_fields: [:name], strategy: :delayed_sidekiq) ``` -------------------------------- ### Nested Strategies Example Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code demonstrates nested strategy usage. It applies the :atomic strategy to a block, and within that, it nests the :urgent strategy for a subset of operations. This allows for different update behaviors within a single operation flow. ```ruby Chewy.strategy(:atomic) do city1.do_update! Chewy.strategy(:urgent) do city2.do_update! city3.do_update! # there will be 2 update index requests for city2 and city3 end city4..do_update! # city1 and city4 will be grouped in one index update request end ``` -------------------------------- ### Define Basic Chewy Index Structure Source: https://github.com/toptal/chewy/blob/master/README.md Creates a basic Chewy index class. This serves as a starting point for defining index configurations. No specific fields or scopes are defined here. ```ruby class UsersIndex < Chewy::Index end ``` -------------------------------- ### Chewy 7.2: Use Index Name in Loader Scope (Ruby) Source: https://github.com/toptal/chewy/blob/master/migration_guide.md Demonstrates the change in Chewy 7.2 where index names are used instead of type names in the loader additional scope. This ensures consistency with the simplified DSL and removes type-specific references. ```ruby # Old syntax: CitiesIndex.filter(...).load(city: {scope: City.where(...)}) # New syntax: CitiesIndex.filter(...).load(cities: {scope: City.where(...)}) ``` -------------------------------- ### Using Scroll API for Large Result Sets in Chewy Source: https://context7.com/toptal/chewy/llms.txt Provides examples of using Chewy's Scroll API (`scroll_batches`, `scroll_hits`, `scroll_objects`) for efficiently processing large numbers of documents without overwhelming memory. ```ruby UsersIndex.scroll_batches(batch_size: 1000) do |batch| batch.each do |user| puts user.email end end UsersIndex.scroll_hits { |hit| puts hit['_source'] } UsersIndex.scroll_objects { |object| puts object.first_name } ``` -------------------------------- ### Boolean Search Queries - Ruby Source: https://context7.com/toptal/chewy/llms.txt Combine multiple query types using boolean logic. This example filters for active users, matches names, and excludes users younger than 18. ```ruby # Boolean queries UsersIndex .filter(term: {active: true}) .query(match: {name: 'John'}) .query.not(range: {age: {lt: 18}}) ``` -------------------------------- ### Set Default Import Options for Chewy Index Source: https://github.com/toptal/chewy/blob/master/README.md Configures default import options for a Chewy index, such as `batch_size`, `bulk_size`, and `refresh`. These options are applied automatically during the import process, providing consistent performance tuning. This example sets these options for a `ProductsIndex`. ```ruby class ProductsIndex < Chewy::Index index_scope Post.includes(:tags) default_import_options batch_size: 100, bulk_size: 10.megabytes, refresh: false field :name field :tags, value: -> { tags.map(&:name) } end ``` -------------------------------- ### Manage Elasticsearch Indices with Chewy in Ruby Source: https://context7.com/toptal/chewy/llms.txt This snippet shows how to perform basic index management operations like checking existence, creating, deleting, purging, and resetting indices using Chewy. It includes examples for creating indices with aliases for zero-downtime resets and the `!` variants that raise exceptions on failure. These operations require a Chewy index class definition. ```ruby # Check if index exists UsersIndex.exists? # => true # Create index UsersIndex.create # Creates index with mappings and settings # => {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"users"} UsersIndex.create! # Same as create but raises exception on failure # Create with suffix for zero-downtime resets UsersIndex.create('2024_01') # Creates index 'users_2024_01' with alias 'users' # Delete index UsersIndex.delete # => {"acknowledged"=>true} UsersIndex.delete! # Same as delete but raises exception if index doesn't exist # Purge (delete and recreate) UsersIndex.purge # Deletes then creates index # => {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"users"} # Reset index (purge + import) UsersIndex.reset! # Performs zero-downtime reset with import # => true # Reset with suffix for zero-downtime UsersIndex.reset!(Time.now.to_i) # Creates new index with suffix, imports data, switches alias ``` -------------------------------- ### Chewy 7.2: Remove Chewy::Type Class Usages (Ruby) Source: https://github.com/toptal/chewy/blob/master/migration_guide.md Shows how to refactor Chewy 7.2 code by removing `Chewy::Type` class usages. The `import!` method calls are updated to use the index name directly instead of the type name. ```ruby # Old syntax: CitiesIndex::City.import!(@cities) # New syntax: CitiesIndex.import!(@cities) ``` -------------------------------- ### Import Data into Elasticsearch Index using Chewy in Ruby Source: https://context7.com/toptal/chewy/llms.txt These examples demonstrate various ways to import data into an Elasticsearch index using Chewy. You can import all records from the `index_scope`, import a specific ActiveRecord scope, an array of objects, or an array of IDs. Efficient ID-based import is highlighted. Requires a Chewy index class and corresponding ActiveRecord models. ```ruby # Import all users from index_scope UsersIndex.import # Imports all User.active records # => true # Import specific scope UsersIndex.import(User.where('rating > 100')) # Imports only users with rating > 100 # Import array of objects users = User.where(active: true).to_a UsersIndex.import(users) # => true # Import specific IDs (adapter fetches objects) UsersIndex.import([1, 2, 3, 42]) # Most efficient way to import by IDs ``` -------------------------------- ### Basic Query Composition in Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Demonstrates the fundamental way to initiate a search query using the `Chewy::Search::Request` class. It shows how to specify a 'match' query on the 'name' field. ```ruby CitiesIndex.query(match: {name: 'London'}) ``` -------------------------------- ### Using Crutches for Performance Optimization in Chewy Source: https://context7.com/toptal/chewy/llms.txt Explains and demonstrates Chewy's 'crutches' feature, which allows defining custom methods to fetch related data efficiently in batches during imports, avoiding N+1 query problems. ```ruby class ProductsIndex < Chewy::Index index_scope Product # Define crutch to fetch categories efficiently crutch :categories do |collection| # collection is the current batch of products data = ProductCategory .joins(:category) .where(product_id: collection.map(&:id)) .pluck(:product_id, 'categories.name') # Convert to hash: {product_id => [category_names]} data.each_with_object({}) do |(id, name), result| (result[id] ||= []).push(name) end end crutch :average_rating do |collection| Review .where(product_id: collection.map(&:id)) .group(:product_id) .average(:rating) end field :name field :category_names, value: ->(product, crutches) { crutches[:categories][product.id] } field :avg_rating, type: 'float', value: ->(product, crutches) { crutches[:average_rating][product.id] } end # When importing, crutches are loaded once per batch ProductsIndex.import # Batch 1: Loads products 1-1000, fetches all categories in 1 query # Batch 2: Loads products 1001-2000, fetches all categories in 1 query # Much faster than N queries per product ``` -------------------------------- ### Ordering, Limiting, and Paginating Search Results in Chewy Source: https://context7.com/toptal/chewy/llms.txt Demonstrates how to apply ordering, limiting, and offsetting to search queries in Chewy for paginated results. This is crucial for efficiently retrieving subsets of data. ```ruby UsersIndex.order(:created_at) .order(rating: {order: :desc}) .limit(20) .offset(40) ``` -------------------------------- ### Define Multi-Field Types in Ruby Source: https://github.com/toptal/chewy/blob/master/README.md Shows how to define a multi-field in Ruby, specifying a type other than 'object' or 'nested' for the root field. It includes an example with an 'ordered' subfield and a 'keyword' subfield. ```ruby field :full_name, type: 'text', value: ->{ full_name.strip } do field :ordered, analyzer: 'ordered' field :untouched, type: 'keyword' end ``` -------------------------------- ### Controlling Request Limits and Ordering in Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Demonstrates how to apply pagination and sorting to search requests using `limit`, `offset`, and `order` methods. This allows precise control over the data returned. ```ruby CitiesIndex.limit(10).offset(30).order(:name, {population: {order: :desc}}) ``` -------------------------------- ### ActiveRecord Model Index Update - Ruby Source: https://context7.com/toptal/chewy/llms.txt Automatically update the 'users' index when a User model changes. This example shows a simple self-reference and an alternative syntax using a method name. ```ruby # app/models/user.rb class User < ApplicationRecord # Simple self-reference update_index('users') { self } # Alternative syntax with method name update_index('users', :self) end ``` -------------------------------- ### Minitest Integration with Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Integrates Chewy with Minitest by including helper modules and configuring indexing strategies. Supports mocking Elasticsearch responses and asserting queries. ```ruby require 'chewy/minitest' include Chewy::Minitest::Helpers # Or configure strategy globally in test_helper.rb # Chewy.strategy(:urgent) # Helper methods available: # mock_elasticsearch_response # mock_elasticsearch_response_sources # assert_elasticsearch_query ``` -------------------------------- ### Using Raw Import for Maximum Performance in Chewy Source: https://context7.com/toptal/chewy/llms.txt Explains Chewy's 'raw_import' option, which allows skipping ActiveRecord instantiation by processing raw hash data directly from the database for significantly faster and more memory-efficient imports. ```ruby class LightweightProduct def initialize(attributes) @attributes = attributes end def name @attributes['name'] end def price @attributes['price'].to_f end # Convert PostgreSQL timestamp directly without DateTime parsing def created_at @attributes['created_at'].tr(' ', 'T') << 'Z' end end class ProductsIndex < Chewy::Index index_scope Product default_import_options raw_import: ->(hash) { LightweightProduct.new(hash) } field :name field :price, type: 'float' field :created_at, type: 'date' end # Import uses raw hashes from database, skipping AR instantiation ProductsIndex.import # Much faster and lower memory usage # Can also pass option explicitly ProductsIndex.import( Product.all, raw_import: ->(hash) { LightweightProduct.new(hash) } ) ``` -------------------------------- ### Bulk Indexing Flow in Ruby (Chewy) Source: https://github.com/toptal/chewy/blob/master/README.md Pseudo-code demonstrating the bulk indexing flow in Ruby for Chewy, processing data in batches and sending them to Elasticsearch using `Chewy.client.bulk`. ```ruby Product.includes(:categories).find_in_batches(1000) do |batch| bulk_body = batch.map do |object| {name: object.name, category_names: object.categories.map(&:name)}.to_json end # here we are sending every batch of data to ES Chewy.client.bulk bulk_body end ``` -------------------------------- ### RSpec Integration for Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Integrate Chewy's RSpec helpers by including `require 'chewy/rspec'` in your `spec_helper.rb`. This provides helpers like `update_index`, `mock_elasticsearch_response`, `mock_elasticsearch_response_sources`, and the `build_query` matcher for testing Elasticsearch interactions. To use specific mocking helpers, include `Chewy::Rspec::Helpers` in your test suite. ```ruby require 'chewy/rspec' # To use mocking helpers: # include Chewy::Rspec::Helpers ``` -------------------------------- ### Bypass Strategy Example Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code illustrates the effect of the :bypass strategy. When active, index updates on object saves are prevented. For instance, saving a City object would not trigger an update in the associated index. ```ruby # When the bypass strategy is active the index will not be automatically updated on object save. # For example, on City.first.save! the cities index would not be updated. ``` -------------------------------- ### Using Witchcraft for Performance Optimization in Chewy Source: https://context7.com/toptal/chewy/llms.txt Introduces Chewy's 'witchcraft' feature, which compiles field definitions into a single, optimized document-returning proc for faster imports. This reduces overhead by creating a single execution path. ```ruby class ProductsIndex < Chewy::Index index_scope Product witchcraft! # Enable compilation field :title field :price, type: 'float' field :tags, value: -> { tags.map(&:name) } field :categories do field :name, value: ->(product, category) { category.name } field :slug, value: ->(product, category) { category.slug } end end # Witchcraft compiles this into approximately: # ->(product, crutches) do # { # title: product.title, # price: product.price, # tags: product.tags.map(&:name), # categories: product.categories.map do |category| # { # name: category.name, # slug: category.slug # } # end # } # end # Import runs faster due to single compiled proc execution ProductsIndex.import ``` -------------------------------- ### Define Chewy Index Scope Source: https://github.com/toptal/chewy/blob/master/README.md Defines a scope for a Chewy index, specifying which records from the associated model should be included. This example uses `User.active` as the scope. You can omit this if you prefer to use PORO objects or do not need a specific scope. ```ruby class UsersIndex < Chewy::Index index_scope User.active # or just model instead_of scope: index_scope User end ``` -------------------------------- ### Configure Chewy Client Settings - Ruby Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code demonstrates how to configure the Chewy client by setting the Elasticsearch host. It's typically placed in an initializer file (`config/initializers/chewy.rb`). ```ruby # config/initializers/chewy.rb Chewy.settings = {host: 'localhost:9250'} # do not use environments ``` -------------------------------- ### Define Geo Point Fields in Ruby (Hash Format) Source: https://github.com/toptal/chewy/blob/master/README.md Illustrates defining a geo_point field using Elasticsearch's mapping in Ruby. This example uses a hash format with 'lat' and 'lon' keys, deriving values from 'latitude' and 'longitude'. ```ruby field :coordinates, type: 'geo_point', value: ->{ {lat: latitude, lon: longitude} } ``` -------------------------------- ### Run Elasticsearch with Docker Source: https://github.com/toptal/chewy/blob/master/README.md Command to run a local Elasticsearch instance using Docker, with security features disabled for convenience. ```shell $ docker run --rm --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" elasticsearch:8.15.0 ``` -------------------------------- ### Loading ORM Objects with Included Associations in Chewy Source: https://context7.com/toptal/chewy/llms.txt Demonstrates how to load ORM objects from search results with eager loading of associations using Chewy's `.load` method. Improves performance by avoiding N+1 queries. ```ruby scope = UsersIndex.query(match: {name: 'John'}) .load(scope: -> { includes(:projects) }) scope.objects # => [#, #, ...] scope.records # => same as objects ``` -------------------------------- ### Chewy Witchcraft™ Index Definition Compilation (Ruby) Source: https://github.com/toptal/chewy/blob/master/README.md Demonstrates how Chewy's Witchcraft™ technology compiles a complex index definition into a single, efficient document-returning proc. This optimizes import performance by reducing the overhead of individual field value computations. ```ruby index_scope Product witchcraft! field :title field :tags, value: -> { tags.map(&:name) } field :categories do field :name, value: -> (product, category) { category.name } field :type, value: -> (product, category, crutch) { crutch.types[category.name] } end ``` ```ruby -> (object, crutches) do { title: object.title, tags: object.tags.map(&:name), categories: object.categories.map do |object2| { name: object2.name, type: crutches.types[object2.name] } end } end ``` -------------------------------- ### Executing Queries and Iterating Over Results in Chewy Source: https://context7.com/toptal/chewy/llms.txt Shows how to execute a search query in Chewy and iterate over the returned results, accessing individual user objects. Useful for processing search outcomes. ```ruby results = UsersIndex.query(match: {name: 'John'}) results.each do |user| puts "#{user.first_name} #{user.last_name}" end ``` -------------------------------- ### Loading ORM/ODM Objects with Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Explains how to load associated ORM/ODM objects using the `load` and `objects` methods. It allows fetching actual data objects instead of just index wrappers. ```ruby CitiesIndex.load(scope: -> { active }).to_a CitiesIndex.load(scope: -> { active }).objects ``` -------------------------------- ### Chewy 7.2: Remove Type Names from String Representations (Ruby) Source: https://github.com/toptal/chewy/blob/master/migration_guide.md Demonstrates how to update string representations in Chewy 7.2 to remove type names. This affects rake tasks and RSpec matchers for updating indexes. Ensure consistency by using only the index name. ```ruby update_index('cities#city') # Old syntax update_index('cities') # New syntax update_index(UsersIndex::User) # Old syntax update_index(UsersIndex) # New syntax # rake tasks: rake chewy:update[cities#city] # Old syntax rake chewy:update[cities] # New syntax ``` -------------------------------- ### Advanced Query and Filter Composition in Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Illustrates chaining multiple query and filter methods, including negation. It shows the flexibility of combining `filter`, `query`, and `not` operations to refine search results. ```ruby CitiesIndex .filter(term: {name: 'Bangkok'}) .query(match: {name: 'London'}) .query.not(range: {population: {gt: 1_000_000}}) ``` -------------------------------- ### Generate Chewy Configuration File Source: https://github.com/toptal/chewy/blob/master/README.md Command to generate the chewy.yml configuration file for different environments. ```shell rails g chewy:install ``` -------------------------------- ### Non-Block Notation for Update Strategies - Ruby Source: https://context7.com/toptal/chewy/llms.txt Illustrates using update strategies without blocks, by setting and then popping the strategy. This provides a more concise way to manage strategy changes. ```ruby # Non-block notation Chewy.strategy(:urgent) user.save! # Updated immediately Chewy.strategy(:bypass) user.save! # Not updated Chewy.strategy.pop user.save! # Updated immediately again ``` -------------------------------- ### Implement Search Query in Users Controller - Ruby Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code defines a `search` action in a UsersController. It uses the UsersIndex to perform a query_string search on specified fields (first_name, last_name, email, etc.) and returns the results as JSON. It also includes a private method for permitting search parameters. ```ruby def search @users = UsersIndex.query(query_string: { fields: [:first_name, :last_name, :email, ...], query: search_params[:query], default_operator: 'and' }) render json: @users.to_json, status: :ok end private def search_params params.permit(:query, :page, :per) end ``` -------------------------------- ### Chewy Raw Import with Lightweight Object (Ruby) Source: https://github.com/toptal/chewy/blob/master/README.md Illustrates the Raw Import feature in Chewy's ActiveRecord adapter, which bypasses ActiveRecord instantiation to improve performance. It shows how to define a lightweight object to mimic ActiveRecord behavior when processing raw data hashes. ```ruby class LightweightProduct def initialize(attributes) @attributes = attributes end def created_at @attributes['created_at'].tr(' ', 'T') << 'Z' end end index_scope Product default_import_options raw_import: ->(hash) { LightweightProduct.new(hash) } field :created_at, 'datetime' ``` -------------------------------- ### Implement Crutches Technology for Associations in Ruby (Chewy) Source: https://github.com/toptal/chewy/blob/master/README.md Demonstrates implementing Chewy's Crutches technology in Ruby to optimize data fetching for associations. It uses a `crutch` block to fetch data with a lightweight query and then uses it in a field. ```ruby class ProductsIndex < Chewy::Index index_scope Product crutch :categories do |collection| # collection here is a current batch of products # data is fetched with a lightweight query without objects initialization data = ProductCategory.joins(:category).where(product_id: collection.map(&:id)).pluck(:product_id, 'categories.name') # then we have to convert fetched data to appropriate format # this will return our data in structure like: # {123 => ['sweets', 'juices'], 456 => ['meat']} data.each.with_object({}) { |(id, name), result| (result[id] ||= []).push(name) } end field :name # simply use crutch-fetched data as a value: field :category_names, value: ->(product, crutches) { crutches[:categories][product.id] } end ``` -------------------------------- ### Import Data with Options - Ruby Source: https://context7.com/toptal/chewy/llms.txt Import data from a User scope with specified batch size, bulk size, refresh, and journaling options. This method allows for fine-grained control over the import process. ```ruby UsersIndex.import( User.all, batch_size: 500, # Process 500 records at a time bulk_size: 5.megabytes, # Split bulk requests at 5MB refresh: true, # Refresh index after import journal: true # Enable journaling ) ``` -------------------------------- ### Counting and Checking Existence of Documents in Chewy Source: https://context7.com/toptal/chewy/llms.txt Shows how to efficiently count documents matching a query and check if any documents exist that match a given filter using Chewy. ```ruby UsersIndex.query(match: {name: 'John'}).count # => 42 UsersIndex.filter(term: {email: 'test@example.com'}).exists? # => true ``` -------------------------------- ### Deploy Indexes with Chewy Source: https://github.com/toptal/chewy/blob/master/README.md The `chewy:deploy` rake task is designed for production deployments. It combines `chewy:upgrade` and `chewy:sync`, performing the synchronization only for indexes that were not reset during the upgrade phase. This task does not support specifying individual indexes. ```bash rake chewy:deploy ``` -------------------------------- ### Enabling Journaling for Data Consistency in Chewy Source: https://context7.com/toptal/chewy/llms.txt Details how to enable journaling in Chewy to record all index operations for later replay, ensuring data consistency. Journaling can be configured globally, per-index, or per-import. ```ruby # config/chewy.yml production: journal: true journal_name: chewy_journal # Or in initializer Chewy.settings[:journal] = true # Or per-index class UsersIndex < Chewy::Index default_import_options journal: true end # Or per-import UsersIndex.import(User.all, journal: true) # Journal records look like: # { # "action": "index", # "object_id": [1, 2, 3], ``` -------------------------------- ### Generate User Model and Migrate Database - Shell Source: https://github.com/toptal/chewy/blob/master/README.md This shell command generates a Rails model for User with first_name, last_name, and email attributes. It is followed by a command to migrate the database, creating the corresponding table. ```shell $ bundle exec rails g model User first_name last_name email $ bundle exec rails db:migrate ``` -------------------------------- ### Chewy Field Skipping with ignore_blank (Ruby) Source: https://github.com/toptal/chewy/blob/master/README.md Shows how to use the `ignore_blank: true` option in Chewy to skip fields that return true for the `.blank?` method, optimizing import by omitting unnecessary data. ```ruby index_scope Country field :id field :cities, ignore_blank: true do field :id field :name field :surname, ignore_blank: true field :description end ``` -------------------------------- ### Import with Error Handling - Ruby Source: https://context7.com/toptal/chewy/llms.txt Import data and handle potential import failures. The `import!` method raises a `Chewy::ImportFailed` exception, providing detailed error messages and specific errors for inspection. ```ruby begin UsersIndex.import!(invalid_data) rescue Chewy::ImportFailed => e puts "Import failed with errors: #{e.message}" puts e.errors.inspect end ``` -------------------------------- ### Use Active Job Strategy Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code demonstrates using the :active_job strategy, which functions similarly to the :atomic strategy but leverages ActiveJob for background processing. It inherits ActiveJob's queue adapter configuration. ```ruby Chewy.strategy(:active_job) do City.popular.map(&:do_some_update_action!) end ``` -------------------------------- ### Mount Uploader and Implement Search in ActiveRecord Model Source: https://github.com/toptal/chewy/wiki/Using-attachment-mapping-field-in-Chewy This Ruby code defines an ActiveRecord model 'Candidate' that uses Carrierwave to mount a 'resume' uploader. It also includes a class method 'search' that utilizes the Chewy index to perform a multi_match query on the 'resume' field. ```ruby class Candidate < ActiveRecord::Base mount_uploader :resume, ResumeUploader def self.search(options) fields = [ 'resume' ] CandidateIndex.query(multi_match: { query: options[:keyword], fields: fields }) end end ``` -------------------------------- ### NewRelic Integration for Chewy Events Source: https://github.com/toptal/chewy/blob/master/README.md Provides a Ruby configuration for integrating Chewy with NewRelic. It defines a custom subscriber (`ChewySubscriber`) that intercepts Chewy events (`import_objects.chewy`, `search_query.chewy`, `delete_query.chewy`) and reports them as Datastore segments within NewRelic transactions. ```ruby require 'new_relic/agent/instrumentation/evented_subscriber' class ChewySubscriber < NewRelic::Agent::Instrumentation::EventedSubscriber def start(name, id, payload) event = ChewyEvent.new(name, Time.current, nil, id, payload) push_event(event) end def finish(_name, id, _payload) pop_event(id).finish end class ChewyEvent < NewRelic::Agent::Instrumentation::Event OPERATIONS = { 'import_objects.chewy' => 'import', 'search_query.chewy' => 'search', 'delete_query.chewy' => 'delete' }. freeze def initialize(*args) super @segment = start_segment end def start_segment segment = NewRelic::Agent::Transaction::DatastoreSegment.new product, operation, collection, host, port if (txn = state.current_transaction) segment.transaction = txn end segment.notice_sql @payload[:request].to_s segment.start segment end def finish if (txn = state.current_transaction) txn.add_segment @segment end @segment.finish end private def state @state ||= NewRelic::Agent::TransactionState.tl_get end def product 'Elasticsearch' end def operation OPERATIONS[name] end def collection payload.values_at(:type, :index) .reject { |value| value.try(:empty?) } .first .to_s end def host Chewy.client.transport.hosts.first[:host] end def port Chewy.client.transport.hosts.first[:port] end end end ActiveSupport::Notifications.subscribe(/.chewy$/, ChewySubscriber.new) ``` -------------------------------- ### Extract Elasticsearch CA Certificate Source: https://github.com/toptal/chewy/blob/master/README.md Command to copy the CA certificate from the Elasticsearch Docker container to the local filesystem. ```shell docker container cp es8:/usr/share/elasticsearch/config/certs/http_ca.crt tmp/ ``` -------------------------------- ### Use Urgent Strategy Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code shows the usage of the :urgent strategy, which is suitable for updating documents one by one. Each update triggers an immediate request to Elasticsearch. ```ruby Chewy.strategy(:urgent) do City.popular.map(&:do_some_update_action!) end ``` -------------------------------- ### Chewy Event Payloads for Import and Search Source: https://github.com/toptal/chewy/blob/master/README.md Illustrates the structure of payloads emitted by Chewy for `import_objects.chewy` and `search_query.chewy` events. These payloads contain information about the index, request details, and statistics or errors related to the operations. ```ruby {index: 30, delete: 5} ``` ```ruby {index: { 'error 1 text' => ['1', '2', '3'], 'error 2 text' => ['4'] }, delete: { 'delete error text' => ['10', '12'] }} ``` -------------------------------- ### Basic Search Query - Ruby Source: https://context7.com/toptal/chewy/llms.txt Perform a basic search query on the UsersIndex using the `match` query type for the 'name' field. This returns a Chewy::Search::Request object. ```ruby # Basic queries UsersIndex.query(match: {name: 'John'}) # => ``` -------------------------------- ### Iterating Wrappers and Objects Simultaneously in Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Shows a method to iterate through both Chewy index wrappers and their corresponding ORM/ODM objects concurrently using `object_hash`. ```ruby scope = CitiesIndex.load(scope: -> { active }) scope.each do |wrapper| scope.object_hash[wrapper] end ``` -------------------------------- ### Configure Chewy Index Settings and Mappings Source: https://github.com/toptal/chewy/blob/master/README.md Sets up advanced index configurations, including custom analyzers (like 'email') within the `settings` block and defines a root object mapping with templates, various field types, and custom value procs. This allows for fine-grained control over how data is indexed and analyzed. ```ruby class UsersIndex < Chewy::Index settings analysis: { analyzer: { email: { tokenizer: 'keyword', filter: ['lowercase'] } } } index_scope User.active.includes(:country, :badges, :projects) root date_detection: false do template 'about_translations.*', type: 'text', analyzer: 'standard' field :first_name, :last_name field :email, analyzer: 'email' field :country, value: ->(user) { user.country.name } field :badges, value: ->(user) { user.badges.map(&:name) } field :projects do field :title field :description end field :about_translations, type: 'object' # pass object type explicitly if necessary field :rating, type: 'integer' field :created, type: 'date', include_in_all: false, value: ->{ created_at } end end ``` -------------------------------- ### Query String Search - Ruby Source: https://context7.com/toptal/chewy/llms.txt Execute a search using the `query_string` query, allowing searches across multiple fields (first_name, last_name, email) with a specified default operator. ```ruby # Query string UsersIndex.query(query_string: { fields: [:first_name, :last_name, :email], query: 'john@example.com', default_operator: 'and' }) ``` -------------------------------- ### Delayed Sidekiq Strategy with Configuration - Ruby Source: https://context7.com/toptal/chewy/llms.txt Configure the `delayed_sidekiq` strategy with parameters like latency, margin, and TTL. This strategy accumulates updates and processes them in batches after a delay. ```ruby # Delayed Sidekiq strategy with latency window class CitiesIndex < Chewy::Index strategy_config delayed_sidekiq: { latency: 3, # Wait 3 seconds before scheduling margin: 2, # Cover 2 seconds of replication lag ttl: 86400 # Chunks expire after 24 hours } end Chewy.strategy(:delayed_sidekiq) do 100.times { City.first.touch } # Accumulates updates and processes in batch end ``` -------------------------------- ### Configure Import Scope Cleanup Behavior Source: https://github.com/toptal/chewy/blob/master/README.md Defines how Chewy handles ActiveRecord's import_scope options (order, offset, limit) during cleanup. Options include warning, raising an exception, or ignoring the check. ```ruby Chewy.import_scope_cleanup_behavior = :ignore ``` -------------------------------- ### Sidekiq Async Update Strategy - Ruby Source: https://context7.com/toptal/chewy/llms.txt Configure the Sidekiq strategy for asynchronous index updates. Updates are queued in Sidekiq for background processing, improving application responsiveness. ```ruby # Sidekiq strategy - async updates via Sidekiq Chewy.strategy(:sidekiq) do User.find_each(&:touch) # Updates are queued in Sidekiq for background processing end # Configure Sidekiq queue Chewy.settings[:sidekiq] = {queue: :low} ``` -------------------------------- ### Rake Task for Upgrading Specific Chewy Indexes Source: https://github.com/toptal/chewy/blob/master/README.md Illustrates how to upgrade specific Chewy indexes by naming them in the `chewy:upgrade` rake task. It also supports exclusion of indexes. ```bash rake chewy:upgrade[users] rake chewy:upgrade[users,cities] rake chewy:upgrade[-users,cities] ``` -------------------------------- ### Apply Journaled Changes with Chewy Source: https://github.com/toptal/chewy/blob/master/README.md The `chewy:journal:apply` task applies journaled changes to specified indexes within a given time frame. The time can be provided in any format parsable by ActiveSupport. Indexes can be optionally specified. ```bash rake chewy:journal:apply["$(date -v-1H -u +%FT%TZ)"] # apply journaled changes for the past hour rake chewy:journal:apply["$(date -v-1H -u +%FT%TZ)",users] # apply journaled changes for the past hour on UsersIndex only ``` -------------------------------- ### Create Missing Indexes with Chewy Source: https://github.com/toptal/chewy/blob/master/README.md The `chewy:create_missing_indexes` rake task creates any newly defined indexes in Elasticsearch that do not yet exist, while skipping those that are already present. This is particularly useful in production-like environments. ```bash rake chewy:create_missing_indexes ``` -------------------------------- ### Querying Across Multiple Indexes in Chewy Source: https://github.com/toptal/chewy/blob/master/README.md Shows how to perform a query that spans across multiple index definitions. The `indices` method allows specifying which indexes to include in the search. ```ruby CitiesIndex.indices(CountriesIndex).query(match: {name: 'Some'}) ``` -------------------------------- ### Chewy Rake Tasks for Index Management Source: https://context7.com/toptal/chewy/llms.txt These Rake tasks provide command-line interface for managing Elasticsearch indices. They allow for resetting, upgrading, updating, syncing, and deploying indices, with options to specify target indices or perform operations on all indices. The reset operation can be zero-downtime, and upgrade only resets if the specification has changed. ```ruby # Reset index (zero-downtime) rake chewy:reset rake chewy:reset[users] rake chewy:reset[users,products] rake chewy:reset[-users,products] # All except users and products # Upgrade (reset only if specification changed) rake chewy:upgrade rake chewy:upgrade[users] # Update (import to existing index) rake chewy:update rake chewy:update[users] # Sync (update only outdated documents) rake chewy:sync rake chewy:sync[users] # Deploy (upgrade + sync) rake chewy:deploy # Create missing indices rake chewy:create_missing_indexes ``` -------------------------------- ### Accessing Search Result Metadata in Chewy Source: https://context7.com/toptal/chewy/llms.txt Illustrates how to retrieve metadata associated with search results, such as total count, maximum score, execution time, and timeout status. Essential for understanding query performance. ```ruby results.total # => 150 results.max_score # => 2.5 results.took # => 5 (milliseconds) results.timed_out? # => false ``` -------------------------------- ### Chewy Configuration: Journal Settings Source: https://github.com/toptal/chewy/blob/master/README.md Configure Chewy journal settings for production to prevent data loss during index resets. The journal logs changes, allowing for re-application after operations like zero-downtime index resets. Be mindful of journal size and consider periodic cleaning. ```yaml production: journal: true journal_name: my_super_journal ``` -------------------------------- ### Rake Task for Upgrading All Chewy Indexes Source: https://github.com/toptal/chewy/blob/master/README.md Shows the command to upgrade all existing Chewy indexes. This task only performs a reset if the index specification (mapping or settings) has changed. ```bash rake chewy:upgrade ``` -------------------------------- ### Chewy Rake Tasks for Journal Management Source: https://context7.com/toptal/chewy/llms.txt These Rake tasks manage the Chewy journal, which is used for zero-downtime resets and catching updates during reset periods. The 'apply' task replays changes from a specified time or index, while the 'clean' task removes old journal entries. Options can be provided to control completion waiting, requests per second, and scroll size. ```ruby # Journal tasks rake chewy:journal:apply["1.hour.ago"] rake chewy:journal:apply["2024-01-15T10:00:00Z",users] rake chewy:journal:clean["7.days.ago"] ``` -------------------------------- ### Nested Update Strategies - Ruby Source: https://context7.com/toptal/chewy/llms.txt Demonstrates nested update strategies, where an outer atomic strategy contains an inner urgent strategy. This allows for different update behaviors within the same block. ```ruby # Nested strategies Chewy.strategy(:atomic) do user1.save! Chewy.strategy(:urgent) do user2.save! # Updated immediately user3.save! # Updated immediately end user4.save! # user1 and user4 updated together at end end ``` -------------------------------- ### Define User Index with Email Analyzer - Ruby Source: https://github.com/toptal/chewy/blob/master/README.md This Ruby code defines a Chewy index for User objects. It includes settings for an email analyzer which tokenizes by keyword and converts to lowercase. It specifies the fields to be indexed: first_name, last_name, and email, with a custom analyzer for email. ```ruby class UsersIndex < Chewy::Index settings analysis: { analyzer: { email: { tokenizer: 'keyword', filter: ['lowercase'] } } } index_scope User field :first_name field :last_name field :email, analyzer: 'email' end ```