How to perform a Search

Structured search with DSL

If find functions are not enough, there is a possibility to perform a structured search using query builder. In a nutshell you can construct any queries, aggregations, etc. that are defined in Elasticsearch Query DSL documentation.

To begin with structured search you will need a Search object. You need to add all the queries and other DSL constructs to this search object and then perform the search from the repository service. There are three specialized find methods dedicated for this task and you may choose between depending on your needs:

method Return Type
findDocuments() Returns an instance of DocumentIterator
findArray() Returns an instance of ArrayIterator
findRaw() Returns an array of raw results with unaltered elasticsearch response structure

For the majority of cases, you will be using findDocuments that returns an iterator with hydrated documents. In addition it provides a convenient way of handling aggregations, that can be accessed via getAggregations() method.

Simple Example

In this example we will search for cities in Lithuania with more than 10K population


$repo = $this->get('es.manager.default.city');
$search = $repo->createSearch();

$termQuery = new TermQuery('country', 'Lithuania');
$search->addQuery($termQuery);

$rangeQuery = new RangeQuery('population', ['from' => 10000]);
$search->addQuery($rangeQuery);

$results = $repo->findDocuments($search);

Important: fields country & population are the field names in elasticsearch type, NOT the document variables.

It will construct a query:


{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {
                        "country": "Lithuania"
                    }
                },
                {
                    "range": {
                        "population": {
                            "from": 10000
                        }
                    }
                }
            ]
        }
    }
}

Important: by default result size in elasticsearch is 10, if you need more set size to your needs.

Setting size or offset is to the search is very easy, because it has getters and setters for these attributes. Therefore to set size all you need to do is to write


$search->setSize(100);

Similarly other properties like Scroll, Timeout, MinScore and more can be defined.

For more query and filter examples take a look at the Elasticsearch DSL library docs. We covered all examples that we found in Elasticsearch Query DSL documentation how to cover in object oriented way.

Searching in Multiple Types

Previous example illustrated the usual case scenario of performing a search in a single type. However if you should ever find yourself in a rear situation where a search needs to be performed on several types at once, you can use a specific search method in manager, that accepts an array with the names of types on which the search needs to be performed.

However, unlike some of the find functions in repository this method returns only the raw results, therefore the use of this method should be minimal and only when needed.

Example of searching in multiple types

Lets say you have City and State documents with title field. Search all cities and states with title "Indiana":

$search = new Search();
$search->addQuery(new TermQuery('title', 'Indiana'));

$results = $manager->execute(
    // Array of documents representing different types
    ['AppBundle:City', 'AppBundle:State'], 
    $search->toArray()
);

Notice, that the second argument needs to be an array, not a Search instance.

Results count

Elasticsearch bundle provides support for Count API. If you need only to count the results, this is a faster way to approach this. Here's an example of how to count cars by red color:


$repo = $this->get('es.manager.default.cars');
$search = $repo->createSearch();

$termQuery = new TermQuery('color', 'red');
$search->addQuery($termQuery);

$count = $repo->count($search);