Laravel and Elasticsearch: connection and basic search setup
14 July 2021
In this article, I would like to share one of our cases of connecting and using Elesticsearch with Laravel on one of our new projects (announcement, advantages among competitors and what kind of project it will be in one of the next posts).
The article will be divided into 2 parts:
1. Connecting to Laravel and implementing a simple full-text search, taking into typos account. Connection, basic setup, mapping, data indexing and a simple query that will return results with errors
2. Data aggregation or as it was called in the 6th version of Elasticsearch - faceted search. It can often be seen in filters of e-commerce projects, namely, counting the number of products when filtering
1. Connection Elasticsearch and basic setup
Technologies and versions:
We use the most current and fresh tools at the moment, now these are:
- Laravel 8,
- PHP 8,
- Elasticsearch 7,
- Mysql 8,
Laravel offers a simple solution to implement full text search on Eloquent Scout models that uses its own observer to automatically reindex the data when data is changed / added / removed from the table. The solution is good, but Scout does not support Elasticsearch out of the box (currently, in the laravel8 version, only Algolia and MeiliSearch are supported) and it does not provide the flexibility that is needed for more complex solutions, such as data aggregation in filters. Well, the "magic" of Laravel with Scout does not give a complete understanding of how to work with search and customize it.
Therefore, based on the above, the choice fell on a package that provides the very same elastic “elasticsearch/elasticsearch”
The process of setting up the server, installing the Laravel, Elasticsearch on the server, setting up the database and filling the table with test data, by which we will set up the search, I will miss, I think this should not be a problem.
First, we will write the host for the elastic in the config of services:
We will search in the products table for the title box, the title box in the table, the varchar box type. To do this, I created 1 million records in advance in this table, especially so many to show the differences in the search speed using Elasticsearch from the standard MySQL like one, if the table contains a large amount of data.
In AppServiceProvider, bind the client class with Elasticsearch, so that you can easily use it in different classes
Create trait Searchable and observer ElasticsearchObserver for the Product model, which will monitor data updates and update the index.
Trait Searchable will look something like this:
Well, let's connect trait Searchable to the model class:
Let's create another console command of the ReindexProduct class to index all records from the products table and write them to elasticsearch:
In the handle method, delete the index if it already exists, create a new index with settings for indexing and write each product to the elastic.
Indexing settings are an important point for flexible search customization to suit your needs, they can be used to describe mappings (this is like data types in MySQL) and analysis, where we describe exactly how the elastic should process our request. Analysis and mappings are a separate large topic in elastic, you can read more in the official documentation, but for a basic example, my settings option is also suitable.
It looks like it's done, let's run the indexing command:
After all the records are indexed, and you have to wait to index 1 million records, you can configure the code logic for the search
Let's create a controller that will accept a request, transfer it to the search service, where the main logic will be and return a view with the data we need:
The service will look something like this:
Elasticsearch already returns the result by relevance, in the buildCollection method we take all the ID of the records, and sort them in the query in the same order as the elastic returned
Well, after all this, the search result page will look something like this:
As you can see in the screenshot, as a result, we got different versions of entries where the word "vitamins" is present, taking into account errors and different endings of the word
The execution speed of such a request will be somewhere around 80-150 milliseconds.
And now let's replace the search from elastic in our control with the classic title like ‘% vitamins%’ and see the speed of such a request.
82 seconds !!! A bit too much, any normal person will wait for the results of this search, well, the result will be without errors consideration.
P.S. It was an implementation of basic search, so to speak, "Elastic for newbies". In the next article, we'll look at data aggregation, which is very important for any e-commerce project.
Author: Arthur Schablevsky
Did you like the article? - Share the link::