Symfony2: elasticsearch autocomplete queries

This is the fifth in a series of posts about using elasticsearch with Symfony2:

  1. Symfony2: Integrating elasticsearch
  2. Symfony2: improving elasticsearch results
  3. Symfony2: elasticsearch custom analyzers
  4. Symfony2: elasticsearch custom repositories
  5. Symfony2: elasticsearch autocomplete queries

In this post I will take a quick a look at how we can create another query for the indexed site entities to provide results for an autocomplete field. I am not going to look at the actual implementation of the autocomplete box or even the formatting of the response since that will depend on the autocomplete implementation.

At the moment the sort of results we are retrieving from the search index will not be suitable for use with autocomplete. For a start, whilst we have used stemming we will not get results when searching for the first part of a word in the name. For example, if we have added a site with Lime Thinking as the name then it will not be returned for a search for L, Li, Lim etc as we will need for autocomplete.

Fortunately this is very easy to remedy with elasticsearch by making our query a text_phrase_prefix query. We can also simplify the query if we assume we are only searching on the name field. So let's make another method in the custom repository for our new query and add the type to the query object:

<?php

namespace LimeThinking\ExampleBundle\SearchRepository;

use FOQ\ElasticaBundle\Repository;

class SiteRepository extends Repository
{
    
    //--

    public function findByPartialName($searchTerm)
    {
        $nameQuery = new \Elastica_Query_Text();
        $nameQuery->setFieldQuery('name', $searchTerm);
        $nameQuery->setFieldParam('name', 'type', 'phrase_prefix');

        return $this->find($nameQuery);
    }

}

This will now return the Lime Thinking site for searches for L, Li, Lim etc as we needed.

It is worth being aware of how this query is processed so that the results make sense. If we search for multiple words then this phrase is not split up but searched for whole. So a search for lime thi will return the Lime Thinking site but a search for lim thi will not find it. The search phrase does not need to match the start of the name though, so a search for thi will return the Lime Thinking entity.

Additionally if we were also to index a site with the name Lime Pickle then we would get both sites for lim but only Lime Thinking on a search for lime thin which differs from the search from previous posts where both would be found for a search for lime thin.