The Elasticsearch value_count aggregation is a single-value metric aggregation that returns the exact total number of values extracted from the documents in a bucket. It counts every non-null occurrence including duplicates, and treats each entry of a multi-valued field as a separate value. Use it to answer "how many ratings did we collect", not "how many unique users rated" - the latter is the cardinality aggregation.
Syntax
GET /reviews/_search
{
"size": 0,
"aggs": {
"total_ratings": {
"value_count": { "field": "rating" }
}
}
}
The result is a single integer at aggregations.total_ratings.value.
Parameters
| Parameter | Default | Description |
|---|---|---|
field |
required (or script) |
Field to count values from. Any aggregatable field. |
script |
- | Use a script instead of a field. The script's emitted values are counted. |
missing |
- | Substitute value used when the field is missing. Counted toward the total. |
There is no precision_threshold or memory tunable - the operation is a straight count over the matched document set.
Examples
Total review entries (not unique reviewers):
"aggs": {
"total_reviews": { "value_count": { "field": "review_id" } }
}
Counts per product, alongside the global total:
"aggs": {
"by_product": {
"terms": { "field": "product_id", "size": 50 },
"aggs": {
"ratings": { "value_count": { "field": "rating" } }
}
},
"ratings_total": { "value_count": { "field": "rating" } }
}
Count values from a multi-valued field (tags), treating each tag as one value:
"value_count": { "field": "tags.keyword" }
Performance Notes
value_count reads doc values for the target field, so the cost is linear in the number of matched documents and effectively free on indexed fields. On text fields, value_count requires fielddata: true, which loads field data into heap - prefer a .keyword sub-field.
The most common production trap is conflating value_count with cardinality. A value_count on user_id returns the number of events; a cardinality on the same field returns the number of distinct users. Mixing those in a dashboard misleads readers. Pulse helps surface query patterns that are creating user-facing inconsistencies in Elasticsearch dashboards and tracks the slow queries that result from misusing fielddata on text fields.
Common Mistakes
- Using value_count when you wanted distinct count - use cardinality instead.
- Running it on a
textfield without.keyword, accidentally enabling fielddata and burning heap. - Setting
missingand forgetting it inflates the count for documents that did not actually have a value. - Reading
_countfrom a parent bucket and assuming it equals the value_count of a sub-field - they differ on multi-valued fields and when some documents are missing the field. - Expecting value_count to count documents. It counts values: a document with three tags contributes 3 to value_count on the tags field.
Frequently Asked Questions
Q: How does value_count differ from cardinality?
A: The value_count aggregation counts every non-null value including duplicates exactly, while the cardinality aggregation returns an approximate count of distinct values. For an event log, value_count gives total events, cardinality gives unique entities.
Q: Does value_count work on multi-valued fields?
A: Yes. Each value in a multi-valued field is counted individually, so a document with five values for the field contributes 5 to the total.
Q: How are null or missing values handled?
A: Documents that lack the field contribute zero unless missing is set, in which case the substitute value is counted once per such document.
Q: Is value_count affected by the search query?
A: Yes. Aggregations always run over the documents matched by the query (or the bucket's docs when nested), not over the entire index. Filter to scope the count.
Q: Can value_count run on a script?
A: Yes, with the script parameter. The number of values the script emits per document is added to the total. Scripted value_count is slower than field-based.
Q: How is value_count different from the bucket doc_count?
A: doc_count counts matched documents; value_count counts non-null values of a specific field. They agree only when the field is single-valued and present on every document.
Related Reading
- Cardinality Aggregation: approximate distinct count.
- Sum Aggregation: total of numeric values rather than count of them.
- Max Aggregation: largest value of a numeric field.
- Terms Aggregation: group documents before counting their values.
- Elasticsearch Query Language: the DSL value_count runs inside.