Symfony2: elasticsearch autocomplete queries
This is the fifth in a series of posts about using elasticsearch with Symfony2:
- Symfony2: Integrating elasticsearch
- Symfony2: improving elasticsearch results
- Symfony2: elasticsearch custom analyzers
- Symfony2: elasticsearch custom repositories
- Symfony2: elasticsearch autocomplete queries
- Symfony2: improving elasticsearch results
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
.