December 8, 2016 0 comments

Use ElasticSearch in your Symfony project

ElasticSearch is an open source clusterised search engine. Based on Apache Lucene and Java technologies, ElasticSearch allows you to search in a pretty huge amount of document in a really short time.


In this tutorial, we will learn how to use ElasticSearch in your Symfony project with the help of Elastica and more precisely with the FOSElasticaBundle.

Let's go ! 


Here you will find the steps you have to follow to use ElasticSearch in your Symfony project.


I am using an Ubuntu system so the following console commands will be Linux based, so I apologize for non-Linux users.


1 - Installing Java

Installing ElasticSearch requires Java on your computer, so if you haven't installed it yet follow those steps.


Open a new terminal and type :


sudo apt-get update


Now you can install OpenJDK


sudo apt-get install openjdk-7-jre


Verify that your JRE is correctly installed with this command


java -version


You should see something like


Output of java -version
java version "1.7.0_79"
OpenJDK Runtime Environment (IcedTea 2.5.6) (7u79-2.5.6-0ubuntu1.14.04.1)
OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)


2 - Downloading and installing Elasticsearch

In your terminal, type the following command to download the version 1.7.2 of ElasticSearch.




Then, install it by using the dpkg command like this


sudo dpkg -i elasticsearch-1.7.2.deb


That's it ! ElasticSearch is now installed. But you must configure it and secure it correctly before using it. I recommend you to follow the Digital Ocean tutorial about ElasticSearch to getting started.


3 - Downloading and installing FOSElasticaBundle

Open a new terminal and in your project directory type the following command to dowload the lastest stable version :


composer require friendsofsymfony/elastica-bundle


In your AppKernel.php file, enable the bundle by adding this line 





class AppKernel extends Kernel
    public function registerBundles()
        $bundles = array(
            new FOS\ElasticaBundle\FOSElasticaBundle(),



You must now configure the bundle. In your app/config/config.yml add this basic configuration for one client with one single index.



        default: { host: locahost, port: 9200 }
        app: ~


Here, an Elastica index called app is available as a service with the key


Now we have to define our types.


By default, FOSElasticaBundle requires each type to be mapped. Each type defined is available as a service with the key fos_elastica.index.my_index.my_type.


FOSElasticaBundle also requires a provider for each type that will notify when an object that maps to a type has been modified.


Here is a config example with Doctrine ORM :



        default: { host: localhost, port: 9200 }
                        username: ~
                        firstname: ~
                        lastname: ~
                        email: ~
                        driver: orm
                        model: Acme\AppBundle\Entity\User
                        provider: ~
                        listener: ~
                        finder: ~


Once your mapping is done, you have to populate your new index with the command 


php app/console fos:elastica:populate


And... that's all ;)

You are now reasy to go with ElasticSearch on your Symfony Project !


4 - Simple search with FOSElasticaBundle

To make simple searches with ElasticSearch, we will need to create a search repository for our User entity and a search object that will help us to search more easily.


Let's start with our search object, UserModel.php, which will contain properties from our app index.



namespace Acme\AppBundle\Model;

class UserModel
    protected $username;

    protected $firstname;

    protected $lastname;

    protected $email;

    public function getUsername()
        return $this->username;

    public function setUsername($username)
        $this->username = $username;

        return $this;

    public function getFirstname()
        return $this->firstname;

    public function setFirstname($firstname)
        $this->firstname = $firstname;
        return $this;

    public function getLastname()
        return $this->lastname;

    public function setLastname($lastname)
        $this->lastname = $lastname;

        return $this;

    public function getEmail()
        return $this->email;

    public function setEmail($email)
        $this->email = $email;

        return $this;

Like all searches, we need a form to collect the informations that we want to search in our index. 

NB : In our example, we will create a form with one field by indexed property, but you can also do a single input form which will search in all the indexed informations.


namespace Acme\AppBundle\Form;

use Acme\AppBundle\Model\UserModel;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;

class UserSearchType extends AbstractType
    public function buildForm(FormBuilderInterface $builder, array $options)
            ->add('username', TextType::class, ['required' => false])
            ->add('firstname', TextType::class, ['required' => false])
            ->add('lastname', TextType::class, ['required' => false])
            ->add('email', EmailType::class, ['required' => false])
            ->add('submit', SubmitType::class)

    public function configureOptions(OptionsResolver $resolver)
            'csrf_protection' => false,
            'data_class' => 'Acme\AppBundle\Model\UserModel'


And now our repository that will use our model :



namespace Acme\AppBundle\Entity\SearchRepository;

use FOS\ElasticaBundle\Repository;
use Acme\AppBundle\Model\UserModel;
use Elastica\Query\BoolQuery;
use Elastica\Query\Terms;
use Elastica\Query;

class UserRepository extends Repository
    $query = new BoolQuery();

    // This searchUser function will build the elasticsearch query to get a list of users that match our criterias
    public function searchUser(UserModel $search)
        if ($search->getUsername() != null && $search->getUsername() != '') {
            $query->addMust(new Terms('username', [$search->getUsername()]));
        if ($search->getFirstname() != null && $search->getFirstname() != '') {
            $query->addMust(new Terms('firstname', [$search->getFirstname()]));
        if ($search->getLastname() != null && $search->getLastname() != '') {
            $query->addMust(new Terms('lastname', [$search->getLastname()]));
        if ($search->getEmail() != null && $search->getEmail() != '') {
            $query->addMust(new Terms('email', [$search->getEmail()]));

        $query = Query::create($query);

        return $this->find($query);


Important : In your User entity, you must specify that the above repository will be used for our elasticsearch searches. To do this, you must add the following annotation in your entity.



use FOS\ElasticaBundle\Configuration\Search;

 * @ORM\Table()
 * @Search(repositoryClass="Acme\UserBundle\Entity\SearchRepository\UserRepository")
class User
    // your entity...



And now the controller, here it is :



namespace Acme\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Acme\UserBundle\Model\UserModel;

class UserController extends Controller
    public function indexAction(Request $request)
        $userSearch = new UserModel();

        $form = $this->createForm(UserSearchType::class, $userSearch);

        $userSearch = $form->getData();

        $elasticaManager = $this->get('fos_elastica.manager');
        $results = $elasticaManager->getRepository('AcmeUserBundle:User')->searchUser($userSearch);

        return $this->render('AcmeUserBundle:User:list.html.twig', [
            'form' => $form->createView(),
            'users' => $results


You now have a working elasticsearch user search form which will return an user list based on your search criterias. It may be a bit complicated at first sight but with a some practice you'll be able to use Elasticsearch for all your searches.


Thanks for reading, I hope this article interested you ! 


As always if you have any questions do not hesitate to use the comment form.



Hugo Soltys

Who is talking to you ?

My name is Hugo, I'm 29 and I'm a Symfony developer since 2013. I love to create websites by myself to learn new technologies or increase my skills. I also like to share my knowledge so I created this blog. I hope you enjoy it :)