Spec-Zone.ru › Elasticsearch 8
›Elasticsearch Guide [8.17] ›Агрегации ›Агрегации метрик

Агрегация boxplot

А boxplot агрегация метрик, которая вычисляет boxplot числовых значений, извлечённых из агрегированных документов. Эти значения могут быть сгенерированы из определённых числовых или польных типов гистограммы в документах.

Агрегация boxplot возвращает важную информацию для построения диаграммы размаха: минимальные, максимальные, медианные, первый квартиль (25-й процентиль) и третий квартиль (75-й процентиль) значения.

Синтаксис

Агрегация boxplot выглядит так:

{
  "boxplot": {
    "field": "load_time"
  }
}

Давайте рассмотрим boxplot, представляющий время загрузки:

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_boxplot": {
            "boxplot": {
                "field": "load_time"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_boxplot: {
        boxplot: {
          field: 'load_time'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_boxplot: {
      boxplot: {
        field: "load_time",
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_boxplot": {
      "boxplot": {
        "field": "load_time" 
      }
    }
  }
}

Поле load_time должно быть числовым полем

Результат будет выглядеть так:

{
  ...

 "aggregations": {
    "load_time_boxplot": {
      "min": 0.0,
      "max": 990.0,
      "q1": 167.5,
      "q2": 445.0,
      "q3": 722.5,
      "lower": 0.0,
      "upper": 990.0
    }
  }
}

В данном случае, нижнее и верхнее значения усов равны min и max. В общем случае, эти значения являются диапазоном 1.5 * IQR, то есть ближайшими значениями к q1 - (1.5 * IQR) и q3 + (1.5 * IQR). Поскольку это приближение, указанные значения могут не являться фактическими значениями из данных, но должны находиться в разумной погрешности от них. Хотя агрегация Boxplot не возвращает непосредственно выбросы, вы можете проверить, существуют ли выбросы с левой стороны по lower > min или с правой стороны по upper < max, и затем запросить их напрямую.

Скрипт

Если вам нужно создать boxplot для значений, которые не индексируются точно, вы должны создать поле выполнения и получить boxplot этого поля. Например, если ваше время загрузки измеряется в миллисекундах, но вы хотите вычислить значения в секундах, используйте поле выполнения для их преобразования:

resp = client.search(
    index="latency",
    size=0,
    runtime_mappings={
        "load_time.seconds": {
            "type": "long",
            "script": {
                "source": "emit(doc['load_time'].value / params.timeUnit)",
                "params": {
                    "timeUnit": 1000
                }
            }
        }
    },
    aggs={
        "load_time_boxplot": {
            "boxplot": {
                "field": "load_time.seconds"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    runtime_mappings: {
      'load_time.seconds' => {
        type: 'long',
        script: {
          source: "emit(doc['load_time'].value / params.timeUnit)",
          params: {
            "timeUnit": 1000
          }
        }
      }
    },
    aggregations: {
      load_time_boxplot: {
        boxplot: {
          field: 'load_time.seconds'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  runtime_mappings: {
    "load_time.seconds": {
      type: "long",
      script: {
        source: "emit(doc['load_time'].value / params.timeUnit)",
        params: {
          timeUnit: 1000,
        },
      },
    },
  },
  aggs: {
    load_time_boxplot: {
      boxplot: {
        field: "load_time.seconds",
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "runtime_mappings": {
    "load_time.seconds": {
      "type": "long",
      "script": {
        "source": "emit(doc['load_time'].value / params.timeUnit)",
        "params": {
          "timeUnit": 1000
        }
      }
    }
  },
  "aggs": {
    "load_time_boxplot": {
      "boxplot": { "field": "load_time.seconds" }
    }
  }
}

Значения Boxplot (обычно) приблизительны

Алгоритм, используемый метрикой boxplot, называется TDigest (представленный Тедом Даннингом в Computing Accurate Quantiles using T-Digests).

Агрегации boxplot и других процентилей также являются недетерминированными. Это означает, что вы можете получить немного разные результаты, используя одни и те же данные.

Сжатие

Приближённые алгоритмы должны балансировать использование памяти и точность оценки. Этот баланс можно регулировать с помощью параметра compression:

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_boxplot": {
            "boxplot": {
                "field": "load_time",
                "compression": 200
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_boxplot: {
        boxplot: {
          field: 'load_time',
          compression: 200
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_boxplot: {
      boxplot: {
        field: "load_time",
        compression: 200,
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_boxplot": {
      "boxplot": {
        "field": "load_time",
        "compression": 200    
      }
    }
  }
}

Сжатие регулирует использование памяти и погрешность приближения

Алгоритм TDigest использует ряд «узлов» для приближения процентилей — чем больше доступных узлов, тем выше точность (и большая потребность в памяти), пропорциональная объёму данных. Параметр compression ограничивает максимальное количество узлов до 20 * compression.

Следовательно, увеличивая значение сжатия, вы можете увеличить точность ваших процентилей за счёт большей потребности в памяти. Более высокие значения сжатия также делают алгоритм медленнее, так как подлежащая структура данных дерева увеличивается в размерах, что приводит к более дорогостоящим операциям. Значение сжатия по умолчанию равно 100.

«Узел» использует примерно 32 байта памяти, поэтому в худшем случае (большое количество данных, поступающих в отсортированном и упорядоченном виде) значения по умолчанию приведут к TDigest размером примерно 64 КБ. На практике данные обычно более случайны, и TDigest будет использовать меньше памяти.

Подсказка выполнения

По умолчанию реализация TDigest оптимизирована для производительности, масштабируется до миллионов или даже миллиардов значений образцов, сохраняя приемлемый уровень точности (в некоторых случаях близка к 1% относительной погрешности для миллионов образцов). Есть возможность использовать реализацию, оптимизированную для точности, установив параметр execution_hint со значением high_accuracy:

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_boxplot": {
            "boxplot": {
                "field": "load_time",
                "execution_hint": "high_accuracy"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_boxplot: {
        boxplot: {
          field: 'load_time',
          execution_hint: 'high_accuracy'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_boxplot: {
      boxplot: {
        field: "load_time",
        execution_hint: "high_accuracy",
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_boxplot": {
      "boxplot": {
        "field": "load_time",
        "execution_hint": "high_accuracy"    
      }
    }
  }
}

Оптимизировать TDigest для точности, ценой производительности

Этот вариант может привести к повышению точности (относительная погрешность близка к 0,01% для миллионов образцов в некоторых случаях), но затем запросы процентилей выполняются в 2-10 раз дольше.

Пропущенное значение

Параметр missing определяет, как должны обрабатываться документы, в которых отсутствует значение. По умолчанию они будут игнорироваться, но также можно обработать их так, как будто у них есть значение.

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "grade_boxplot": {
            "boxplot": {
                "field": "grade",
                "missing": 10
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      grade_boxplot: {
        boxplot: {
          field: 'grade',
          missing: 10
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    grade_boxplot: {
      boxplot: {
        field: "grade",
        missing: 10,
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "grade_boxplot": {
      "boxplot": {
        "field": "grade",
        "missing": 10     
      }
    }
  }
}

Документы без значения в поле grade попадут в тот же диапазон, что и документы со значением 10.

© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/search-aggregations-metrics-boxplot-aggregation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API