Skip to the content.

Bucket Aggregations

Bucket aggregations group documents into buckets based on criteria like terms, date ranges, or numeric ranges.

Terms Aggregation

Groups documents by field values:

<?php
use Zvonchuk\Elastic\Search\Aggregations\AggregationBuilders;

$termsAgg = AggregationBuilders::terms('categories')
    ->field('category.keyword')
    ->size(10);  // Return top 10 categories

This generates:

{
  "categories": {
    "terms": {
      "field": "category.keyword",
      "size": 10
    }
  }
}

Date Histogram Aggregation

Groups documents by date intervals:

<?php
use Zvonchuk\Elastic\Search\Aggregations\AggregationBuilders;
use Zvonchuk\Elastic\Search\Aggregations\Bucket\DateHistogramBuilder;

$dateHistogram = AggregationBuilders::dateHistogram('sales_per_month')
    ->field('created_at')
    ->calendarInterval(DateHistogramBuilder::MONTH)
    ->minDocCount(0);  // Include empty buckets

This generates:

{
  "sales_per_month": {
    "date_histogram": {
      "field": "created_at",
      "calendar_interval": "1M",
      "min_doc_count": 0
    }
  }
}

Histogram Aggregation

Groups numeric values into buckets of a specified interval:

<?php
use Zvonchuk\Elastic\Search\Aggregations\AggregationBuilders;

$histogramAgg = AggregationBuilders::histogram('price_ranges')
    ->field('price')
    ->interval(50)    // 0-50, 50-100, 100-150, etc.
    ->minDocCount(1); // Only include buckets with at least one document

Percentiles Aggregation

Calculates percentiles of a numeric field:

<?php
use Zvonchuk\Elastic\Search\Aggregations\AggregationBuilders;

$percentilesAgg = AggregationBuilders::percentiles('response_percentiles')
    ->field('response_time')
    ->percents([50, 95, 99])  // Median, 95th percentile, 99th percentile
    ->compression(100)
    ->keyed(true);

Geo Hash Grid Aggregation

Groups geo-points into buckets using geohash:

<?php
use Zvonchuk\Elastic\Search\Aggregations\AggregationBuilders;

$geoHashGridAgg = AggregationBuilders::geoHashGrid('location_grid')
    ->field('location')
    ->precision(5);  // Geohash precision level

Example: Using Bucket Aggregations

Here’s a practical example of using bucket aggregations:

<?php
use Zvonchuk\Elastic\Core\SearchRequest;
use Zvonchuk\Elastic\Search\Builder\SearchSourceBuilder;
use Zvonchuk\Elastic\Query\QueryBuilders;
use Zvonchuk\Elastic\Search\Aggregations\AggregationBuilders;
use Zvonchuk\Elastic\Search\Aggregations\Bucket\DateHistogramBuilder;

// Create a query for active orders
$query = QueryBuilders::termQuery('status', 'completed');

// Set up the search with multiple bucket aggregations
$searchSource = new SearchSourceBuilder();
$searchSource->query($query);
$searchSource->size(0);  // Only interested in aggregations

// Add terms aggregation for product categories
$searchSource->aggregation(
    AggregationBuilders::terms('top_categories')
        ->field('category.keyword')
        ->size(5)
);

// Add date histogram for orders over time
$searchSource->aggregation(
    AggregationBuilders::dateHistogram('orders_over_time')
        ->field('order_date')
        ->calendarInterval(DateHistogramBuilder::MONTH)
);

// Execute the search
$request = new SearchRequest('orders');
$request->source($searchSource);
$response = $client->search($request);

// Process the aggregation results
$aggs = $response->getAggregations();

// Process top categories
echo "Top Categories:\n";
foreach ($aggs['top_categories']['buckets'] as $bucket) {
    $category = $bucket['key'];
    $count = $bucket['doc_count'];
    echo "- $category: $count orders\n";
}

// Process orders over time
echo "\nOrders Over Time:\n";
foreach ($aggs['orders_over_time']['buckets'] as $bucket) {
    $month = date('Y-m', $bucket['key'] / 1000);
    $count = $bucket['doc_count'];
    echo "- $month: $count orders\n";
}