Rails and elasticsearch for beginners - follow up

An article, posted about 9 years ago filed in elasticsearch, rails, search, linux, server, development, ruby, gem, tech & programming.

In a previous post I described how simple integrating elasticsearch is with Rails for beginners. You could’ve been happy with the fact that you now have implemented full text search, but that too basic set up probably doesn’t work that much better than adding a column to your model, throwing in all text in it and running a LIKE query (although elasticsearch does try to rearrange the results a bit).

In this post I will learn you two things that makes elasticsearch worth it.

Analyzers

Analyzers add some fuzziness to your searches. First, make sure your analyzer is in the right language, this will improve your results. You add the following bit to your model (I typically place it just below where the scopes and validation are defined).

settings index: { number_of_shards: 1 } do
  mappings do
    indexes :title, analyzer: 'dutch', index_options: 'offsets'
    indexes :body, analyzer: 'dutch', index_options: 'offsets'
  end
end

If you’d already indexed your articles you should reindex them first:

Article.__elasticsearch__.refresh_index!
Article.import

(this is actually not recommended for production updates, but it works for now when testing)

Then, change from the default ‘match’ filter to a fuzzy search:

Article.search( query: {
    fuzzy: {
        _all: "elasticseerch"
    }
})

And you’ll probably find the article titled ‘elasticsearch’ (if present)

Note: in the previous article I directly mapped the results to ActiveRecord objects, you get these by calling the .records method after the search.

Filtering

Another important feature of elastic search is filtering. You may want to filter only on articles within the category ‘search’. You can filter the articles in the following way:

Article.search(
    query: {
        filtered: {
            query: {
                match_all: {}
            },
            filter: {
                term: {
                    "category.title"=>"search"
                }
            }
        }
    }
)

Tip: Do know that the regular strings get some processing, hence even when your category is named “Search”, the default analyzer has lowered the case down to “search”. You can turn this off if you want one on one matching…

Filtering and searching

On most websites you’ll probably want to offer both filtering and searching. We can simply combine the two above queries:

Article.search(
    query: {
	    filtered: {
	        query: {
	            fuzzy: {
	                _all: "elasticseerch"
	            }
	        },
	        filter: {
	            term: {
	                "category.title"=>"search"
	            }
	        }
	    }
	}
)

If you want to increase the number of results returned, increase the default limit:

Article.search(
    query: {
        filtered: {
            query: {
                fuzzy: {
                    _all: "elasticseerch"
                }
            },
            filter: {
                term: {
                    "category.title"=>"search"
                }
            }
        }
    }, 
    limit: 50
)

I hope this got you started on the basics. As you might have recognized, the queries and filters can be nested (I am unaware of any limits to the nesting depth, but it will obviously come at some performance cost). For more advanced queries, I hope I can now safely point you towards the Elastic Search docs. Good luck!

Op de hoogte blijven?

Maandelijks maak ik een selectie artikelen en zorg ik voor wat extra context bij de meer technische stukken. Schrijf je hieronder in:

Mailfrequentie = 1x per maand. Je privacy wordt serieus genomen: de mailinglijst bestaat alleen op onze servers.