We might have heard about a lot many gems which let us implement search functionality in our rails application; for example: searchkick, elasticsearch-rails, ransack and finally, sunspot to work with solr search engine. All these gems have their own advantages. Both searchkick and elasticsearch use redis to search the data as well as need to perform a ‘reindex’ while inserting new data. In one of my recent projects, I happened to use a gem called as Textacular. It’s simple and very easy to use.
Textacular Gem:
It is a gem that provides full text search capabilities for PostgreSQL Database. It basically caters to extend the scope of the work performed by activerecord, in a rather friendly manner. It works on heroku as well.
This gem works only on PostgreSQL
For working with it, let’s first grab the latest textacular gem from https://rubygems.org/gems/textacular and add it to the gemfile.
gem 'textacular'
bundle install
Textacular gem provides us with quite a few methods to search the data. So, all our models have the access to use those methods.
basic_search
advanced_search
fuzzy_search
Usage:
Basic_search: It searches based on the input text.
User.basic_search(‘abc’) # Searches on all the model column attributes
User.basic_search(last_name: 'abc', first_name: 'xyz')
Advanced_search: Here, we can use postgres syntaxes like !, & and | (and, or and, not) and then, some others based on the requirement. It converts user’s search DSL into Pg syntax. For this, we need to make sure that the necessary exceptions should be used to handle the syntax errors.
User.advanced_search(last_name: 'text1|text2’) - It searches with the text1 or text2 on last_name on User model.
User.advanced_search(last_name: '!text2’) - It searches for the records whose last_name is not text2.
These searches can be chainable as shown below:
User.advanced_search(last_name: 'text1|text2’).basic_search(last_name: 'abc', first_name: 'xyz')
Fuzzy_search:
We need to install pg_trgm module to work with fuzzy_search. Run the command below to install this module. It searches for partial appearance of your text in the DB.
rake textacular:create_trigram_migration
rake db:migrate
Now, we are ready to use fuzzy_search.
User.fuzzy_search('Lorem')
By default, fuzzy search, searches for the records which are 30% of the search text matches with respect to the entire content. We can set this threshold limit by using the command below.
ActiveRecord::Base.connection.execute("SELECT set_limit(0.6);")
So, it expects 60% of search text to match with the original content.
We can use OR condition to search on multiple columns. Need to pass a hash with columns with input text as param one and pass second param as a false. It takes AND, if you miss second param or if it True.
User.fuzzy_search({first_name: 'user', last_name: 'test'}, false)
User.fuzzy_search(first_name: ‘user’, last_name: 'test') - It takes AND condition.
By default, the Textacular searches in all text and string columns. We can alter its default behaviour by overriding the searchable_columns method in the model.
def self.searchable_columns
[:title, :body]
end
We can override self.searchable_language in the model to set proper dictionary settings.
def self.searchable_language
'arabic'
end
Please check gem official documents for global search and more.