Elastica

A PHP client for elasticsearch.

Fork me on GitHub

Search-documents

Search documents

With some documents in the index we can start searching. A basic search is executing a query against elasticsearch. The result of a query then can be filtered by defining some filters. Additionally you can aggregate Documents to create metadata or graphs based on filters. For further information check out the Query DSL and the Aggregations reference. In this example we don’t use all possible options to keep it simple.

The Search class is one of most flexible entry points in Elastica to query elasticsearch form your PHP application. Other classes which can execute queries are: Index, Type, Bulk and even Client for raw queries.

Search class provides useful methods and constants to configure your search query.

1
$search = new Elastica\Search($client);

Add indices and types

1
2
3
4
5
6
$search
    ->addIndex('GB')
    ->addIndex($indexUS) // $indexUS instanceof Elastica\Index

    ->addType('user')
    ->addType($typeTweet); // $typeTweet instanceof Elastica\Type

Add search options

1
2
3
$search
    ->setOption(Search::OPTION_TIMEOUT, '100ms')
    ->setOption(Search::OPTION_ROUTING, 'user_1,user2');

Query

You may have noticed that the most important part of a search query is actually missing: the query. Because this is the most complicated (and fun) part of elasticsearch, Elastica provides a bunch of classes to help you creating that part of your search query.

Query is dedicated to the “body” of request body search. It provides a method for every configuration field:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$query = new Elastica\Query();

$query
    ->setFrom(50)
    ->setSize(10)
    ->setSort(['name' => 'asc'])
    ->setSource(['obj1.*', 'obj2.'])
    ->setFields(['name', 'created'])
    ->setScriptFields($scriptFields) // $scriptFields instanceof Elastica\ScriptFields
    ->setHighlight(['fields' => 'content'])
    ->setRescore($rescoreQuery) // $rescoreQuery instanceof Elastica\Rescore\AbstractRescore
    ->setExplain(true)
    ->setVersion(true)
    ->setPostFilter($filterTerm) // $$filterTerm instanceof Elastica\Filter\AbstractFilter
    ->setMinScore(0.5);

$search->setQuery($query);

Also it’s possible to provide an array to create a new search. This array follows Elasticsearch request structure, e.g.:

1
2
3
4
5
6
7
$query = new \Elastica\Query([
    'query' => [
        'term' => ['_all' => 'search term'],
    ],
]);

$search->setQuery($query);

For further information check out the official documentation.

And for very basic searches it’s also possible to just search for a term:

1
2
3
$query = new \Elastica\Query('search term');

$search->setQuery($query);

QueryBuilder

In order to set query, aggregation, suggest and facet query parts, you can create the corresponding classes like

1
2
3
4
5
6
7
$query->setQuery(new \Elastica\Query\MatchAll());

$query->addAggregation(new \Elastica\Aggregation\Range('name'));

$query->setSuggest(new \Elastica\Suggest(new \Elastica\Suggest\Term('name', 'field')));

$query->setFacets([new \Elastica\Facet\Range('name')]);

to create more complex queries use QueryBuilder to construct all of the different parts of your query. QueryBuilder is going to check, whether the method you want to use is available in your current elasticsearch version or not.

1
2
3
4
5
6
7
// version checks against latest DSL version
$qb = new \Elastica\QueryBuilder();

// version checks against 1.3 DSL version
$qb = new \Elastica\QueryBuilder(
    new \Elastica\QueryBuilder\Version\Version130()
);

Now just start to write your query as you would write the raw JSON. If your IDE is configured correctly you should experience a handy way to access all available methods in elasticsearch.

1
2
3
4
5
6
7
8
9
10
11
12
$query->setQuery(
    $qb->query()->filtered(
        $qb->query()->match_all(),
        $qb->filter()->bool()
            ->addMust(
                $qb->filter()->term(['field' => 'term'])
            )
            ->addMustNot(
                $qb->filter()->exists('field1')
            )
    )
);
1
2
3
4
5
6
7
$query->addAggregation(
    $qb->aggregation()->date_histogram('histogram', 'date_field', 'interval')
        ->addAggregation(
            $qb->aggregation()->sum('sum')
                ->setField('field')
        )
);
1
2
3
$query->setSuggest(new Suggest(
    $qb->suggest()->term('name', 'field')
));

Facets are not supported by QueryBuilder. You should really have a look into aggregations, they are much powerful then facets!

Retrieve results

To execute your search query just choose one of the following methods:

count API

1
$numberOfEntries = $search->count(); // returns int 

search API

1
$resultSet = $search->search(); // returns Elastica\ResultSet

scan and scroll API

1
2
3
foreach ($search->scanAndScroll() as $scrollId => $resultSet) {
    // ... handle Elastica\ResultSet
}

In $resultSet all the resulting documents are stored. You can get them together with some statistics easily.

1
2
3
4
5
6
$results = $resultSet->getResults();
$totalResults = $resultSet->getTotalHits();

foreach ($results as $result) {
    // $result instanceof Elastica\Result
}

or process aggregation result

1
2
3
4
5
6
7
8
// Get aggregations from the result of the search query
$aggregations = $resultSet->getAggregations();

// Notice, that "range" is the same name you chose
// when the aggregation was defined.
foreach ($aggregations['range']['buckets'] as $bucket) {
    // ... handle array $bucket 
}