Meilisearch Rails

repository·main·Indexed 18 days ago

https://github.com/meilisearch/meilisearch-rails

A Ruby on Rails integration for the Meilisearch search engine. It provides automatic indexing via model callbacks, model-based configuration for searchable, filterable, and sortable attributes, and support for basic, multi-search, and federated searches. Compatible with ActiveRecord, Mongoid, and Sequel, it supports pagination backends including kaminari, will_paginate, and pagy.

Tokens
11.7K
Snippets
45
Records
51
Agent score
62%

What's inside meilisearch-rails

  1. Configure queries for federated search

    main

    The queries parameter in federated_search can be structured in several ways depending on how you want to identify the search targets:

    1. Array of Hashes: Each hash contains a query string q and an optional scope or index_uid.
    2. Hash with Model Keys: Use the model class as the key. Records will be automatically loaded using that model's scope.
    3. Hash with Index UIDs: Use string or symbol index names as keys. You can still provide a scope to ensure the returned results are loaded as model instances.

    Precedence for determining the search index:

    1. The index_uid option within a query hash.
    2. The index associated with the model provided in the scope (e.g., Book.index.uid).
    3. The key used in a hash-style query.
    # Using an array of hashes with explicit index_uid
    results = Meilisearch::Rails.federated_search(
      queries: [
        { q: 'Harry', scope: Book, index_uid: 'fantasy_books' }
      ]
    )
    
    # Using a hash with models as keys (automatic loading)
    results = Meilisearch::Rails.federated_search(
      queries: {
        Book => { q: 'Harry' },
        Manga => { q: 'Attack on Titan' }
      }
    )
    
    # Using a hash with index names as keys
    results = Meilisearch::Rails.federated_search(
      queries: {
        'books_production' => { q: 'Harry', scope: Book.all }
      }
    )
  2. Install Meilisearch Rails

    main

    To use Meilisearch with Ruby on Rails, add the gem to your Gemfile or install it via the command line.

    Requirements:

    • Ruby 3.0 or later
    • Rails 6.1 or later

    Using Bundler (Recommended): Add this to your Gemfile:

    source 'https://rubygems.org'
    
    gem 'meilisearch-rails'

    Then run bundle install.

    Using gem command:

    gem install meilisearch-rails
  3. Sync Meilisearch with related records

    main

    To ensure changes in a related record trigger a re-index of the parent, use touch and after_touch.

    ActiveRecord Pattern:

    1. Use touch: true on the belongs_to association.
    2. Use an after_save hook on the parent to touch children.
    3. Use after_touch :index! on the child model.

    Sequel Pattern:

    1. Use the touch plugin.
    2. Use after_touch :index! on the child model.
    # ActiveRecord
    class Author < ActiveRecord::Base
      include Meilisearch::Rails
      has_many :books
      after_save { books.each(&:touch) }
    end
    
    class Book < ActiveRecord::Base
      include Meilisearch::Rails
      belongs_to :author, touch: true
      after_touch :index!
    
      meilisearch do
        attribute :author do
          author.name
        end
      end
    end
  4. Configure pagination with kaminari or will_paginate

    main

    To use kaminari or will_paginate for backend pagination, specify the :pagination_backend in your Meilisearch::Rails.configuration. Once configured, calling the search method on your model will return paginated results.

    Defaults:

    • Hits per page: 20
    • You can override this using the hits_per_page parameter in your search call.
    Meilisearch::Rails.configuration = {
      meilisearch_url: 'YourMeilisearchUrl',
      meilisearch_api_key: 'YourMeilisearchAPIKey',
      pagination_backend: :kaminari # or :will_paginate
    }
    
    # Usage in controller
    @hits = Book.search('harry potter', hits_per_page: 10)
    
    # Usage in views (kaminari)
    <%= paginate @hits %>
  5. Configure Meilisearch Rails

    main

    You must configure the MEILISEARCH_HOST and MEILISEARCH_API_KEY to connect the gem to your Meilisearch instance.

    You can create the configuration file manually at config/initializers/meilisearch.rb or use the provided Rake task to generate it automatically.

    Manual Configuration:

    Meilisearch::Rails.configuration = {
      meilisearch_url: ENV.fetch('MEILISEARCH_HOST', 'http://localhost:7700'),
      meilisearch_api_key: ENV.fetch('MEILISEARCH_API_KEY', 'YourMeilisearchAPIKey')
    }

    Using Rake Task:

    bin/rails meilisearch:install

    Advanced Configuration: You can also adjust request timeouts and retry logic:

    Meilisearch::Rails.configuration = {
      meilisearch_url: 'YourMeilisearchUrl',
      meilisearch_api_key: 'YourMeilisearchAPIKey',
      timeout: 2,
      max_retries: 1,
    }
  6. Run Rails commands in the playground container

    main

    You can execute Rails-related commands or interact with the Rails console inside the playground environment by running a bash session in the container.

    To enter the container: docker-compose run --rm playground bash

    Once inside, you can start the Rails console with: bundle exec rails c

    docker-compose run --rm playground bash
    root@49ebb83ca4bf:/home/app# bundle exec rails c
  7. Deactivate Meilisearch HTTP connections

    main

    You can disable HTTP requests to Meilisearch to prevent errors in certain environments or moments.

    • Globally via configuration: Set active: false in the configuration block.
    • Programmatically: Use Meilisearch::Rails.deactivate! to disable all calls. It is recommended to use the block version to ensure the state is restored automatically.
    • Manually: Use Meilisearch::Rails.activate! to re-enable connections.
    # Global configuration
    Meilisearch::Rails.configuration = {
      meilisearch_url: '...',
      meilisearch_api_key: '...',
      active: false
    }
    
    # Programmatic block (Recommended)
    Meilisearch::Rails.deactivate! do
      # Meilisearch calls here are dismissed without error
    end
    
    # Manual activation
    Meilisearch::Rails.activate!
  8. Configure pagination with pagy

    main

    To use pagy for pagination, follow these steps:

    1. Add pagy to your Gemfile.
    2. Create config/initializers/pagy.rb with require 'pagy/extras/meilisearch'.
    3. Extend your model with Pagy::Meilisearch.
    4. Use pagy_search in your controller and pagy_meilisearch to generate the pagination object.

    Note: Do not set pagination_backend in Meilisearch::Rails.configuration when using pagy.

    # config/initializers/pagy.rb
    require 'pagy/extras/meilisearch'
    
    # app/models/book.rb
    class Book < ApplicationRecord
      include Meilisearch::Rails
      extend Pagy::Meilisearch
      meilisearch
    end
    
    # app/controllers/books_controller.rb
    def search
      hits = Book.pagy_search(params[:query])
      @pagy, @hits = pagy_meilisearch(hits, items: 25)
    end
    
    # app/views/books/search.html.erb
    <%== pagy_nav(@pagy) %>
  9. Add search capabilities to a model

    main

    To enable Meilisearch for a model (ActiveRecord, Mongoid, or Sequel), include the Meilisearch::Rails module and define a meilisearch block.

    Important: Even if you want to use all default options, you must declare an empty meilisearch block in your model.

    Defining attributes to index: By default, if the block is empty, all attributes are sent. To limit what is indexed, use the attribute method:

    class Book < ActiveRecord::Base
      include Meilisearch::Rails
    
      meilisearch do
        attribute :title, :author # only 'title' and 'author' will be sent to Meilisearch
      end
    end

    Once configured, meilisearch-rails automatically synchronizes your database data with Meilisearch using model callbacks.

    class Book < ActiveRecord::Base
      include Meilisearch::Rails
    
      meilisearch do
        attribute :title, :author
      end
    end
  10. Set up the Meilisearch::Rails playground environment

    main

    To set up a local development environment for the playground, use Docker. Run the following commands within a container instance created by docker-compose run --rm playground bash:

    1. bundle install to install Ruby dependencies.
    2. yarn install to install JavaScript dependencies.
    3. bundle exec rails db:setup to initialize the database.

    After setup, start the application using:

    docker-compose up playground

    The application will be available at http://0.0.0.0:3000.

    docker-compose run --rm playground bash
    # Inside the container:
    bundle install
    yarn install
    bundle exec rails db:setup
    
    # From your host machine:
    docker-compose up playground
  11. How indexable constraints work

    main

    When configuring which records should be sent to Meilisearch, you can use :if and :unless options. The Meilisearch::Rails::Utilities.indexable? method evaluates these constraints.

    Constraints can be:

    • A Symbol or String: The method name to be called on the record (e.g., :published?).
    • An Enumerable: A list of constraints where all must pass (logical AND).
    • A Proc/Callable: A block that receives the record and returns a boolean.

    If a constraint is provided as an Enumerable, the record is only considered indexable if every inner constraint evaluates to true.

  12. Configure Meilisearch index settings in the model

    main

    You can define index-specific settings like searchable, filterable, and sortable attributes directly within the meilisearch block of your model. This ensures your index is configured correctly according to Meilisearch's requirements.

    Supported settings inside the block:

    • searchable_attributes: List of attributes to search.
    • filterable_attributes: List of attributes to allow filtering.
    • sortable_attributes: List of attributes to allow sorting.
    • ranking_rules: Custom ranking rules.
    • synonyms: Define attribute synonyms.
    • attributes_to_highlight: Attributes to highlight in search results.
    • attributes_to_crop: Attributes to crop.
    • crop_length: Length for cropped attributes.
    • faceting: Facet configuration.
    • pagination: Pagination settings.
    • proximity_precision: Precision for proximity search.

    Example:

    class Book < ApplicationRecord
      include Meilisearch::Rails
    
      meilisearch do
        searchable_attributes [:title, :author, :publisher, :description]
        filterable_attributes [:genre]
        sortable_attributes [:title]
        ranking_rules [
          'proximity',
          'typo',
          'words',
          'attribute',
          'sort',
          'exactness',
          'publication_year:desc'
        ]
        synonyms nyc: ['new york']
    
        attributes_to_highlight ['*']
        attributes_to_crop [:description]
        crop_length 10
        faceting max_values_per_facet: 2000
        pagination max_total_hits: 1000
        proximity_precision 'byWord'
      end
    end