Using Sylius and Elasticsearch for products filter

BitBag
BitBag Publications
5 min readMar 24, 2019

Product filtering is a tricky topic in any eCommerce application. End users always want to specify what set of products they are looking for and the role of the eCommerce platform is to provide the possibility to match these products with specific criteria. On the other hand, the users want to access the data instantly, which might get hard when you need to deal with a lot of relations in a classic database engine like MySQL. Having an external engine that does not depend on relations and allows you to access the data fast & easy might be a way to go. For this purpose, Elasticsearch is often the right answer.

What is Elasticsearch?

Elasticsearch is an open source search engine and key-value storage, that is scalable & flexible at the same time. It allows creating documents (indexes) with a huge amount of data and allows filtering it with built-in query builders, similar to ones you are familiar with from relational databases.

How does Elasticsearch work with Sylius?

We created a Sylius Elasticsearch integration that works with all the Product related fields. It is based on FOSElasticaBundle, which is a Symfony wrapper for a commonly used PHP library - Elastica. The bundle itself integrates with Doctrine and allows you to work with the whole Symfony & Doctrine stack quite easily. What we have done is we prepared an Elasticsearch indexes on top of Sylius models including Product, Taxon, Attribute and Option. You can check it out here, on our official Github organization.

In a nutshell, it transforms the relation data into something like this:

Having such data in the Elasticsearch gives us the possibility to filter a huge amount of data in real time.

By default there are 3 indexes created:

  • bitbag_shop_products for product-related data,
  • bitbag_attribute_taxons for attributes available within a specific taxon,
  • bitbag_option_taxons for options available within a specific taxon.

The architecture

If you follow the installation guide, as a result, you will get the nice feature set from the main image of this blog post representing the products filter, which will override the default Sylius route for products list with the one pointing to our listing.

Property builders

As mentioned previously, the plugin is based on FOS Elastica Bundle. Friends Of Symfony Elastica offers a nice event-based architecture for mapping Doctrine Entities (or models) including Sylius ones. By default, the plugin listens to all Doctrine events for each entity configured for a specific index. In order to map the entity object to an Elasticsearch document, we introduced something we called property builders.

Here’s an example of what a property builder looks like:

It is a simple tagged service that is an event subscriber at the same time, which means that it needs to be tagged with kernel.event_subscriber in case you don’t use autowire. Take a look at some default property builders here.

Query builders

What we also introduced in this plugin are query builders. Query builders are basically simple services that wrap the Elasticsearch queries into Symfony services on top of available Elastica query objects. If you take a look at these source files of ruflin/Elastica library and compare it with this Elastica documentation page you will quickly notice that the Elastica library’s query part is an object-oriented wrapper for Elasticsearch queries that you’d normally need to build in JSON and execute after you open the ES connection and do all the boring stuff. Kudos to Nicolas Ruflin, who is the author of this package!

Here’s an example of what a HasTaxonQueryBuilder looks like:

Straightforward, isn’t it?

Customization

Here comes the fun part. What if you want to customize the plugin and add some data to the default index, build the query or create some new filter forms?

Services

You can customize each part of this plugin by decorating the Symfony services. You can take a look at what services are available with our plugin by executing the bin/console debug:container | grep bitbag.sylius_elasticsearch_plugin command. If you don’t know how to use the decorator pattern in Symfony yet, take a look here. It is extremely useful while working with Sylius.

Parameters

When it comes to the parameters, things are no different here. You can execute the bin/console debug:container --parameters | grep bitbag command and create corresponding parameters in your local config file, for instance _sylius.yaml . You might want to do it if you want to override the default localhost:9200 Elasticsearch connection.

Property builders

As for the property builders, you can either decorate the existing ones or create a new one and tag it with kernel.event_describer . Take a look at the services examples mentioned in the property builders architecture section above.

Query builders

If you want to customize the query builders, you can decorate the existing ones, especially the ShopProductsQueryBuilder. It is the main query for the products list. Currently, only decoration is the way to customize it, but in the future, we plan to introduce a cleaner tag oriented architecture.

Forms

You can customize forms by using the Symfony form extension pattern (again, quite useful while working with Sylius). You can take a look at what forms are included by default here. You might also want to decorate the default ListProductsAction, which is the controller responsible for all form & request data handling.

If you want to create a new form, you’d need to extend the AbstractFilterType proxy class and tag the form as a form service (in case you don’t autowire). The NameFilterType might be a good example.

Templates

There is a bunch of templates that you can override as well. Take a look at these source files. If you’re not familiar with the customization process yet, read this official Sylius documentation page. The target plugin directory you will need to create in your bundles/templates or theme folder is BitBagSyliusElasticsearchPlugin.

Summary

We use the plugin for most of our Sylius-standard projects. It’s proven to work under a huge amount of data, like 200k products. At some point, you might need to adjust the Elasticsearch a little to deal with a large amount of data, but overall — the implementation is there. It is tested with Behat & PHPSpec, so as long as the Travis build is green, you’re quite safe while using it. The plugin is currently considered the official Sylius integration with Elasticsearch, as you can read here.

You can support the plugin development in various ways. Obviously, we’d appreciate creating issues and opening interesting discussions on Github alongside with pull requests. Leaving a star is also a nice way to say that you appreciated our work. You can also recommend BitBag as Sylius experts so that we get more exciting projects that help us building more open source plugins like this one 🙂.

--

--

BitBag
BitBag Publications

BitBag is an eCommerce Software Engineering company experienced in solving complex business problems with the best of bread technology.