Create custom Aggregation¶
Create aggregation class¶
To create a custom Aggregation, create an aggregation class. In the following example, an aggregation groups the location query results by the location priority:
1 2 3 4 5 6 7 8 9 10 11 12 | |
The PriorityRangeAggregation class extends AbstractRangeAggregation.
The name of the class indicates that it aggregates the results by using the Range aggregation.
An aggregation must implement the Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation interface or inherit one of following abstract classes:
Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\AbstractRangeAggregationIbexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\AbstractStatsAggregationIbexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\AbstractTermAggregation
An aggregation can also implement one of the following interfaces:
Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\FieldAggregation, based on content fieldIbexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\LocationAggregation, based on content locationIbexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\RawAggregation, based on details of the index structure
Aggregation definition
An aggregation definition must contain at least the name of an aggregation and optional aggregation parameters, such as, for example, the path (string) that is used to limit aggregation results to a specific subtree, content type identifier, or field definition identifier, which is mapped to the search index field name.
Aggregation definition must be independent of the search engine used.
A custom aggregation requires that the following elements are provided:
- An aggregation visitor that returns an array of results
- A result extractor that transforms raw aggregation results from the search engine into
AggregationResultobjects
In simpler cases, you can apply one of the built-in visitors that correspond to the aggregation type.
The example below uses RangeAggregationVisitor:
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 | |
The visitor is created by SearchFieldAggregationVisitorFactory.
You provide it with two arguments:
- The aggregation class in
aggregationClass - The field name in search index in
searchIndexFieldName
In this example, the field is priority_i which exists only for locations.
Tag the service with ibexa.search.solr.query.location.aggregation.visitor.
For content-based aggregations, use the ibexa.search.solr.query.content.aggregation.visitor tag.
Tag the service with ibexa.search.elasticsearch.query.location.aggregation_visitor.
For content-based aggregations, use the ibexa.search.elasticsearch.query.content.aggregation.visitor tag.
For the result extractor, you can use the built-in RangeAggregationResultExtractor and provide it with the aggregation class in the aggregationClass parameter.
Tag the service with ibexa.search.solr.query.location.aggregation.result.extractor.
As $keyMapper to transform raw keys into more usable objects or scalar values, use IntRangeAggregationKeyMapper
or create your own implementing RangeAggregationKeyMapper.
1 2 3 4 5 6 7 8 | |
For other cases, a TermAggregationKeyMapper interface is also available.
Tag the service with ibexa.search.elasticsearch.query.location.aggregation.result.extractor.
1 2 3 4 5 6 7 | |
You can use a different type of aggregation, followed by respective visitor and extractor classes:
- Range
Ibexa\Solr\Query\Common\AggregationVisitor\RangeAggregationVisitorIbexa\Solr\ResultExtractor\AggregationResultExtractor\RangeAggregationResultExtractor
- Stats (count, minimum, maximum, average, sum)
Ibexa\Solr\Query\Common\AggregationVisitor\StatsAggregationVisitorIbexa\Solr\ResultExtractor\AggregationResultExtractor\StatsAggregationResultExtractor
- Term
Ibexa\Solr\Query\Common\AggregationVisitor\TermAggregationVisitorIbexa\Solr\ResultExtractor\AggregationResultExtractor\TermAggregationResultExtractor
- Range
Ibexa\ElasticSearchEngine\Query\AggregationVisitor\RangeAggregationVisitorIbexa\ElasticSearchEngine\Query\ResultExtractor\AggregationResultExtractor\RangeAggregationResultExtractor
- Stats (count, minimum, maximum, average, sum)
Ibexa\ElasticSearchEngine\Query\AggregationVisitor\StatsAggregationVisitorIbexa\ElasticSearchEngine\Query\ResultExtractor\AggregationResultExtractor\StatsAggregationResultExtractor
- Term
Ibexa\ElasticSearchEngine\Query\AggregationVisitor\TermAggregationVisitorIbexa\ElasticSearchEngine\Query\ResultExtractor\AggregationResultExtractor\TermAggregationResultExtractor
In a more complex use case, you must create your own visitor and extractor.
Create aggregation visitor¶
The aggregation visitor must implement Ibexa\Contracts\Solr\Query\AggregationVisitor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
The aggregation visitor must implement Ibexa\Contracts\ElasticSearchEngine\Query\AggregationVisitor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
The canVisit() method checks whether the provided aggregation is of the supported type (in this case, your custom PriorityRangeAggregation).
The visit() method returns an array of results.
Finally, register the aggregation visitor as a service.
Tag the aggregation visitor with ibexa.search.solr.query.location.aggregation.visitor:
1 2 3 4 | |
For content-based aggregations, use the ibexa.search.solr.query.content.aggregation.visitor tag.
Tag the aggregation visitor with ibexa.elasticsearch.query.location.aggregation_visitor:
1 2 3 4 | |
For content-based aggregations, use the ibexa.search.elasticsearch.query.content.aggregation.visitor tag.
Create result extractor¶
You must also create a result extractor, which implements Ibexa\Contracts\Solr\ResultExtractor\AggregationResultExtractor that transforms raw aggregation results from Solr into AggregationResult objects:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | |
The canVisit() method checks whether the provided aggregation is of the supported type (in this case, your custom PriorityRangeAggregation).
The extract() method converts the raw data provided by the search engine to a RangeAggregationResult object.
You must also create a result extractor, which implements Ibexa\Contracts\ElasticSearchEngine\Query\AggregationResultExtractor that transforms raw aggregation results from Elasticsearch into AggregationResult objects:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | |
The supports() method checks whether the provided aggregation is of the supported type (in this case, your custom PriorityRangeAggregation).
The extract() method converts the raw data provided by the search engine to a RangeAggregationResult object.
Finally, register the result extractor as a service.
Tag the result extractor with ibexa.search.solr.query.location.aggregation.result.extractor:
1 2 3 4 | |
For content-based aggregations, use the ibexa.search.solr.query.content.aggregation.result.extractor tag.
Tag the result extractor with ibexa.elasticsearch.query.location.aggregation_result_extractor:
1 2 3 4 | |
For content-based aggregations, use the ibexa.search.elasticsearch.query.content.aggregation.result.extractor tag.