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.
In this example we will search for cities in Lithuania with more than 10K population
$index = $this->get('MyIndexClass::class');
$search = $index->createSearch();
$termQuery = new TermQuery('country', 'Lithuania');
$search->addQuery($termQuery);
$rangeQuery = new RangeQuery('population', ['from' => 10000]);
$search->addQuery($rangeQuery);
$results = $index->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 it in the object oriented way.
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:
$index = $this->get('MyIndexClass::class');
$search = $index->createSearch();
$termQuery = new TermQuery('color', 'red');
$search->addQuery($termQuery);
$count = $index->count($search);
The only way how we think it would be possible is to use same alias according several indexes.
Moreover, the structure of the documents should be the same; otherwise, it won't create document objects.
Notice, that the second argument needs to be an array, not a
Search
instance.