From 3fb680964ceefae1c3787228747b65b50fdfd997 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Thu, 11 Sep 2014 01:26:15 +0200 Subject: [PATCH] add aggregation, stats and suggester to elasticsearch fixes #4452, close #4452 --- extensions/elasticsearch/CHANGELOG.md | 3 + extensions/elasticsearch/Query.php | 171 ++++++++++-------------------- extensions/elasticsearch/QueryBuilder.php | 15 ++- 3 files changed, 68 insertions(+), 121 deletions(-) diff --git a/extensions/elasticsearch/CHANGELOG.md b/extensions/elasticsearch/CHANGELOG.md index b9fd5f6..50a8148 100644 --- a/extensions/elasticsearch/CHANGELOG.md +++ b/extensions/elasticsearch/CHANGELOG.md @@ -11,6 +11,9 @@ Yii Framework 2 elasticsearch extension Change Log - Enh #4048: Added `init` event to `ActiveQuery` classes (qiangxue) - Enh #4086: changedAttributes of afterSave Event now contain old values (dizews) - Enh: Make error messages more readable in HTML output (cebe) +- Enh: Added support for query stats (cebe) +- Enh: Added support for query suggesters (cebe) +- Chg #4451: Removed support for facets and replaced them with aggregations (cebe, tadaszelvys) - Chg: asArray in ActiveQuery is now equal to using the normal Query. This means, that the output structure has changed and `with` is supported anymore. (cebe) - Chg: Deletion of a record is now also considered successful if the record did not exist. (cebe) - Chg: Requirement changes: Yii now requires elasticsearch version 1.0 or higher (cebe) diff --git a/extensions/elasticsearch/Query.php b/extensions/elasticsearch/Query.php index ab0eeb1..cb515e9 100644 --- a/extensions/elasticsearch/Query.php +++ b/extensions/elasticsearch/Query.php @@ -135,11 +135,29 @@ class Query extends Component implements QueryInterface /** * @var array The highlight part of this search query. This is an array that allows to highlight search results * on one or more fields. + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-request-highlighting.html */ public $highlight; - public $facets = []; + /** + * @var array List of aggregations to add to this query. + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html + */ + public $aggregations = []; + /** + * @var array the 'stats' part of the query. An array of groups to maintain a statistics aggregation for. + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#stats-groups + */ + public $stats = []; + /** + * @var array list of suggesters to add to this query. + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html + */ + public $suggest = []; + /** + * @inheritdoc + */ public function init() { parent::init(); @@ -244,8 +262,6 @@ class Query extends Component implements QueryInterface return $result; } - // TODO add query stats http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#stats-groups - // TODO add scroll/scan http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#scan /** @@ -342,137 +358,72 @@ class Query extends Component implements QueryInterface } /** - * Adds a facet search to this query. - * @param string $name the name of this facet - * @param string $type the facet type. e.g. `terms`, `range`, `histogram`... - * @param string|array $options the configuration options for this facet. Can be an array or a json string. + * Adds a 'stats' part to the query. + * @param array $groups an array of groups to maintain a statistics aggregation for. * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-query-facet.html + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search.html#stats-groups */ - public function addFacet($name, $type, $options) + public function stats($groups) { - $this->facets[$name] = [$type => $options]; + $this->stats = $groups; return $this; } /** - * The `terms facet` allow to specify field facets that return the N most frequent terms. - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. - * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-facet.html - */ - public function addTermFacet($name, $options) - { - return $this->addFacet($name, 'terms', $options); - } - - /** - * Range facet allows to specify a set of ranges and get both the number of docs (count) that fall - * within each range, and aggregated data either based on the field, or using another field. - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. - * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-range-facet.html - */ - public function addRangeFacet($name, $options) - { - return $this->addFacet($name, 'range', $options); - } - - /** - * The histogram facet works with numeric data by building a histogram across intervals of the field values. - * Each value is "rounded" into an interval (or placed in a bucket), and statistics are provided per - * interval/bucket (count and total). - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. - * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-histogram-facet.html - */ - public function addHistogramFacet($name, $options) - { - return $this->addFacet($name, 'histogram', $options); - } - - /** - * A specific histogram facet that can work with date field types enhancing it over the regular histogram facet. - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. - * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-date-histogram-facet.html - */ - public function addDateHistogramFacet($name, $options) - { - return $this->addFacet($name, 'date_histogram', $options); - } - - /** - * A filter facet (not to be confused with a facet filter) allows you to return a count of the hits matching the filter. - * The filter itself can be expressed using the Query DSL. - * @param string $name the name of this facet - * @param string $filter the query in Query DSL - * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-filter-facet.html - */ - public function addFilterFacet($name, $filter) - { - return $this->addFacet($name, 'filter', $filter); - } - - /** - * A facet query allows to return a count of the hits matching the facet query. - * The query itself can be expressed using the Query DSL. - * @param string $name the name of this facet - * @param string $query the query in Query DSL + * Sets a highlight parameters to retrieve from the documents. + * @param array $highlight array of parameters to highlight results. * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-query-facet.html + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html */ - public function addQueryFacet($name, $query) + public function highlight($highlight) { - return $this->addFacet($name, 'query', $query); + $this->highlight = $highlight; + return $this; } /** - * Statistical facet allows to compute statistical data on a numeric fields. The statistical data include count, - * total, sum of squares, mean (average), minimum, maximum, variance, and standard deviation. - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. + * Adds an aggregation to this query. + * @param string $name the name of the aggregation + * @param string $type the aggregation type. e.g. `terms`, `range`, `histogram`... + * @param string|array $options the configuration options for this aggregation. Can be an array or a json string. * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-statistical-facet.html + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html */ - public function addStatisticalFacet($name, $options) + public function addAggregation($name, $type, $options) { - return $this->addFacet($name, 'statistical', $options); + $this->aggregations[$name] = [$type => $options]; + return $this; } /** - * The `terms_stats` facet combines both the terms and statistical allowing to compute stats computed on a field, - * per term value driven by another field. - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. + * Adds an aggregation to this query. + * + * This is an alias for [[addAggregation]]. + * + * @param string $name the name of the aggregation + * @param string $type the aggregation type. e.g. `terms`, `range`, `histogram`... + * @param string|array $options the configuration options for this aggregation. Can be an array or a json string. * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-stats-facet.html + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.x/search-aggregations.html */ - public function addTermsStatsFacet($name, $options) + public function addAgg($name, $type, $options) { - return $this->addFacet($name, 'terms_stats', $options); + return $this->addAggregation($name, $type, $options); } /** - * The `geo_distance` facet is a facet providing information for ranges of distances from a provided `geo_point` - * including count of the number of hits that fall within each range, and aggregation information (like `total`). - * @param string $name the name of this facet - * @param array $options additional option. Please refer to the elasticsearch documentation for details. + * Adds a suggester to this query. + * @param string $name the name of the suggester + * @param string|array $definition the configuration options for this suggester. Can be an array or a json string. * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-geo-distance-facet.html + * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html */ - public function addGeoDistanceFacet($name, $options) + public function addSuggester($name, $definition) { - return $this->addFacet($name, 'geo_distance', $options); + $this->suggest[$name] = $definition; + return $this; } - // TODO add suggesters http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html - // TODO add validate query http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-validate.html // TODO support multi query via static method http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-multi-search.html @@ -532,18 +483,6 @@ class Query extends Component implements QueryInterface } /** - * Sets a highlight parameters to retrieve from the documents. - * @param array $highlight array of parameters to highlight results. - * @return static the query object itself - * @see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html - */ - public function highlight($highlight) - { - $this->highlight = $highlight; - return $this; - } - - /** * Sets the source filtering, specifying how the `_source` field of the document should be returned. * @param array $source the source patterns to be selected. * @return static the query object itself diff --git a/extensions/elasticsearch/QueryBuilder.php b/extensions/elasticsearch/QueryBuilder.php index 0373c49..0b04e4b 100644 --- a/extensions/elasticsearch/QueryBuilder.php +++ b/extensions/elasticsearch/QueryBuilder.php @@ -98,19 +98,24 @@ class QueryBuilder extends \yii\base\Object $parts['filter'] = $whereFilter; } - if($query->highlight) { + if (!empty($query->highlight)) { $parts['highlight'] = $query->highlight; } + if (!empty($query->aggregations)) { + $parts['aggregations'] = $query->aggregations; + } + if (!empty($query->stats)) { + $parts['stats'] = $query->stats; + } + if (!empty($query->suggest)) { + $parts['suggest'] = $query->suggest; + } $sort = $this->buildOrderBy($query->orderBy); if (!empty($sort)) { $parts['sort'] = $sort; } - if (!empty($query->facets)) { - $parts['facets'] = $query->facets; - } - $options = []; if ($query->timeout !== null) { $options['timeout'] = $query->timeout;