postgresqlspreesolidus

How to add pg_search to the seach form in Solidus frontend?


I have a question regarding pg_search: I installed the gem on solidus 2.9 and added a product_decorator.rb model like this:

Spree::Product.class_eval do
  include PgSearch::Model

  pg_search_scope :search, against: [:name, :description, :meta_description, :meta_keywords],
    using: {tsearch: {dictionary: "english"}}

end

It works fine in rails console.

How can I make it work when I use the search field in solidus' frontend? I tried adding it to the product controller but can't seem to make it work. Thanks!

UPDATE

So after kennyadsl's comments I have this:

#lib/mystore/products_search.rb

module MyStore
  class ProductSearch < Spree::Core::Search::Base

    def retrieve_products
      Spree::Product.pg_search
    end
  end
end
#models/spree/product_decorator.rb

Spree::Product.class_eval do
  include PgSearch::Model

  pg_search_scope :search, against: [:name, :description, :meta_description, :meta_keywords], using: {tsearch: {dictionary: "english"}}

  def self.text_search(keywords)
        if keywords.present?
      search(keywords)
    else
      Spree::Product.all
    end
  end       

end
#controllers/products_controller.rb

def index
  @searcher = build_searcher(params.merge(include_images: true))
  @products = @searcher.retrieve_products(params)
end

Solution

  • By default, products search is performed through the Spree::Core::Search::Base class, but it's configurable so you can create your own class that inherits from that one:

    module Spree
      module Core
        module Search
          class PgSearch < Spree::Core::Search::Base
            def retrieve_products
              PgSearch.multisearch(...)
            end
          end
        end
      end
    end
    

    To see what's available in that class you can refer to the original implementation here:

    https://github.com/solidusio/solidus/blob/eff22e65691a64d2ce0bf8a919d8456010360753/core/lib/spree/core/search/base.rb

    Once you've added your own logic, you can use the new class to perform search by adding this line into a config/initializers/spree.rb:

    Spree::Config.searcher_class = Spree::Core::Search::PgSearch
    

    UPDATE

    After some back and forth with Ignacio, this is a working version to perform a basic search with PgSearch in the Solidus storefront:

    # app/models/spree/product_decorator.rb
    
    Spree::Product.class_eval do
      include PgSearch::Model
    
      pg_search_scope :keywords, 
        against: [:name, :description, :meta_description, :meta_keywords],
        using: { tsearch: { dictionary: "english" } }
    end
    
    # lib/spree/core/search/pg_search.rb
    
    module Spree
      module Core
        module Search
          class PgSearch < Spree::Core::Search::Base
            def retrieve_products
              Spree::Product.pg_search_by_keywords(@properties[:keywords])
            end
          end
        end
      end
    end
    
    # config/initializers/spree.rb
    
    Spree::Config.searcher_class = Spree::Core::Search::PgSearch