cardinality-aggregation.asciidoc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. [[search-aggregations-metrics-cardinality-aggregation]]
  2. === Cardinality Aggregation
  3. A `single-value` metrics aggregation that calculates an approximate count of
  4. distinct values. Values can be extracted either from specific fields in the
  5. document or generated by a script.
  6. Assume you are indexing books and would like to count the unique authors that
  7. match a query:
  8. [source,js]
  9. --------------------------------------------------
  10. {
  11. "aggs" : {
  12. "author_count" : {
  13. "cardinality" : {
  14. "field" : "author"
  15. }
  16. }
  17. }
  18. }
  19. --------------------------------------------------
  20. ==== Precision control
  21. This aggregation also supports the `precision_threshold` and `rehash` options:
  22. experimental[The `precision_threshold` and `rehash` options are specific to the current internal implementation of the `cardinality` agg, which may change in the future]
  23. [source,js]
  24. --------------------------------------------------
  25. {
  26. "aggs" : {
  27. "author_count" : {
  28. "cardinality" : {
  29. "field" : "author_hash",
  30. "precision_threshold": 100, <1>
  31. "rehash": false <2>
  32. }
  33. }
  34. }
  35. }
  36. --------------------------------------------------
  37. <1> The `precision_threshold` options allows to trade memory for accuracy, and
  38. defines a unique count below which counts are expected to be close to
  39. accurate. Above this value, counts might become a bit more fuzzy. The maximum
  40. supported value is 40000, thresholds above this number will have the same
  41. effect as a threshold of 40000.
  42. Default value depends on the number of parent aggregations that multiple
  43. create buckets (such as terms or histograms).
  44. <2> If you computed a hash on client-side, stored it into your documents and want
  45. Elasticsearch to use them to compute counts using this hash function without
  46. rehashing values, it is possible to specify `rehash: false`. Default value is
  47. `true`. Please note that the hash must be indexed as a long when `rehash` is
  48. false.
  49. ==== Counts are approximate
  50. Computing exact counts requires loading values into a hash set and returning its
  51. size. This doesn't scale when working on high-cardinality sets and/or large
  52. values as the required memory usage and the need to communicate those
  53. per-shard sets between nodes would utilize too many resources of the cluster.
  54. This `cardinality` aggregation is based on the
  55. http://static.googleusercontent.com/media/research.google.com/fr//pubs/archive/40671.pdf[HyperLogLog++]
  56. algorithm, which counts based on the hashes of the values with some interesting
  57. properties:
  58. * configurable precision, which decides on how to trade memory for accuracy,
  59. * excellent accuracy on low-cardinality sets,
  60. * fixed memory usage: no matter if there are tens or billions of unique values,
  61. memory usage only depends on the configured precision.
  62. For a precision threshold of `c`, the implementation that we are using requires
  63. about `c * 8` bytes.
  64. The following chart shows how the error varies before and after the threshold:
  65. image:images/cardinality_error.png[]
  66. For all 3 thresholds, counts have been accurate up to the configured threshold
  67. (although not guaranteed, this is likely to be the case). Please also note that
  68. even with a threshold as low as 100, the error remains under 5%, even when
  69. counting millions of items.
  70. ==== Pre-computed hashes
  71. If you don't want Elasticsearch to re-compute hashes on every run of this
  72. aggregation, it is possible to use pre-computed hashes, either by computing a
  73. hash on client-side, indexing it and specifying `rehash: false`, or by using
  74. the special `murmur3` field mapper, typically in the context of a `multi-field`
  75. in the mapping:
  76. [source,js]
  77. --------------------------------------------------
  78. {
  79. "author": {
  80. "type": "string",
  81. "fields": {
  82. "hash": {
  83. "type": "murmur3"
  84. }
  85. }
  86. }
  87. }
  88. --------------------------------------------------
  89. With such a mapping, Elasticsearch is going to compute hashes of the `author`
  90. field at indexing time and store them in the `author.hash` field. This
  91. way, unique counts can be computed using the cardinality aggregation by only
  92. loading the hashes into memory, not the values of the `author` field, and
  93. without computing hashes on the fly:
  94. [source,js]
  95. --------------------------------------------------
  96. {
  97. "aggs" : {
  98. "author_count" : {
  99. "cardinality" : {
  100. "field" : "author.hash"
  101. }
  102. }
  103. }
  104. }
  105. --------------------------------------------------
  106. NOTE: `rehash` is automatically set to `false` when computing unique counts on
  107. a `murmur3` field.
  108. NOTE: Pre-computing hashes is usually only useful on very large and/or
  109. high-cardinality fields as it saves CPU and memory. However, on numeric
  110. fields, hashing is very fast and storing the original values requires as much
  111. or less memory than storing the hashes. This is also true on low-cardinality
  112. string fields, especially given that those have an optimization in order to
  113. make sure that hashes are computed at most once per unique value per segment.
  114. ==== Script
  115. The `cardinality` metric supports scripting, with a noticeable performance hit
  116. however since hashes need to be computed on the fly.
  117. [source,js]
  118. --------------------------------------------------
  119. {
  120. "aggs" : {
  121. "author_count" : {
  122. "cardinality" : {
  123. "script": "doc['author.first_name'].value + ' ' + doc['author.last_name'].value"
  124. }
  125. }
  126. }
  127. }
  128. --------------------------------------------------
  129. TIP: The `script` parameter expects an inline script. Use `script_id` for indexed scripts and `script_file` for scripts in the `config/scripts/` directory.