Analyze case fields
Kibana stores case template values (called extended fields) together in case.extended_fields, keyed as <name>_as_<type> (for example, effort_as_integer). These keys don't appear as separate fields in Discover or Lens, so you query them in one of three ways.
Legacy custom fields live in a separate case.customFields field, which you can't query with ES|QL.
| Method | Tool | Use it when |
|---|---|---|
| Typed fields | Discover and Lens | You want to explore and visualize fields with numeric, date, and boolean operators. |
FIELD_EXTRACT |
ES|QL | You want to query any field, including one without a typed field. |
terms aggregation |
Elasticsearch API | You want to aggregate directly on a field key. |
A typed field is a version of a case field that the managed Case Analytics data view publishes with a specific data type, named case.<name>_as_<type> (for example, case.effort_as_integer). The data view publishes one for each templated or global field. Because a typed field has a real type, you get numeric, date, and boolean operators in Discover and Lens instead of text matching on the raw value stored in case.extended_fields.
Kibana publishes a typed field only when both of these are true:
- A current template uses the field, or the global field library defines it.
- The field name uses only letters, digits, and underscores. Fields created before Elastic Stack 9.5 might have hyphenated keys, so Kibana doesn't publish a typed field for them.
A newly added field can take a short time to appear. To refresh the field list immediately, restart Kibana or ask an administrator to refresh the data view.
Fields without a typed field are still stored in case.extended_fields, so you can always reach them with FIELD_EXTRACT or a terms aggregation.
FIELD_EXTRACT returns a string, so cast the value to the type you need, then aggregate:
FROM .cases
| EVAL effort = FIELD_EXTRACT(case.extended_fields, "effort_as_integer")::double
| WHERE effort IS NOT NULL
| STATS avg_effort = AVG(effort), with_value = COUNT(effort), total = COUNT(*)
Use a terms aggregation to group directly on a field key, even if it has no typed field:
GET .cases/_search
{
"size": 0,
"aggs": {
"by_effort": {
"terms": { "field": "case.extended_fields.effort_as_integer" }
}
}
}