Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msievers/e9421cee6479294f5af5c1eedc1c8f79 to your computer and use it in GitHub Desktop.
Save msievers/e9421cee6479294f5af5c1eedc1c8f79 to your computer and use it in GitHub Desktop.
A simple, sql only, multi model search
The idea is, to have models adhere to a convention, which stats, that there has to be a field "searchable_tokens",
which includes searchable tokens. Now, we can simply have a (virtual) model/table `search_results`, which can be
unioned with "casted selects" of each model we want to search. The casted selects make the columns of each model to fit
into the schema of the search result.
Mixed with ActiveRecord's polymorphic associations, the result is an ActiveRecord relation with elements, which points to
their respective subject.
# db/migrate/20170317064203_create_search_results.rb
#
# This table is not meant to have any rows, it's more like a virtual table
#
class CreateSearchResults < ActiveRecord::Migration[5.0]
def change
create_table :search_results do |t|
t.integer :subject_id
t.string :subject_type
t.text :searchable_tokens
end
end
end
# app/models/search_result.rb
#
class SearchResult < ApplicationRecord
belongs_to :subject, polymorphic: true
end
# - the selects force the results in a schema that can be unioned with the search_results table
# - because we declared the model to be polymorphic associated to a subject, the actual hit can be accessed via `subject`
# If your search_results table has timestamps, than you have to select created_at, updated_at, too
companies = Company.where("searchable_tokens LIKE '%micha%'").select("NULL as id, id AS subject_id, 'Company' AS subject_type, searchable_tokens")
users = User.where("searchable_tokens LIKE '%micha%'").select("NULL as id, id AS subject_id, 'User' AS subject_type, searchable_tokens")
saerch_result = SearchResult.all.union(companies).union(users)
search_result.first.subject # => Company
search_result.second.subject # => User
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment