Skip to content

Commit

Permalink
feat: add value_as_string to min/max aggregations
Browse files Browse the repository at this point in the history
min/max aggregations return also value_as_string, which can be useful when
running over date fields:

{
  "aggregations": {
    "max-example": {
      "value": 1770336000000,
      "value_as_string": "2026-02-06"
    },
    "min-example": {
      "value": 1716422400000,
      "value_as_string": "2024-05-23"
    }
  }
}

It is possible to access them now.
  • Loading branch information
mcenkar committed Jun 6, 2024
1 parent 9d98e99 commit c908a28
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@ object SignificantTermsAggResult {
)
}

case class AvgAggResult(name: String, valueOpt: Option[Double]) extends MetricAggregation {
case class AvgAggResult(name: String, valueOpt: Option[Double], valueAsString: Option[String]) extends MetricAggregation {
def value: Double = valueOpt.get
}
case class SumAggResult(name: String, valueOpt: Option[Double]) extends MetricAggregation {
case class SumAggResult(name: String, valueOpt: Option[Double], valueAsString: Option[String]) extends MetricAggregation {
def value: Double = valueOpt.get
}
case class MinAggResult(name: String, value: Option[Double]) extends MetricAggregation
case class MaxAggResult(name: String, value: Option[Double]) extends MetricAggregation
case class MinAggResult(name: String, value: Option[Double], valueAsString: Option[String]) extends MetricAggregation
case class MaxAggResult(name: String, value: Option[Double], valueAsString: Option[String]) extends MetricAggregation
case class ValueCountResult(name: String, valueOpt: Option[Double]) extends MetricAggregation {
def value: Double = valueOpt.get
}
Expand Down Expand Up @@ -241,7 +241,7 @@ trait HasAggregations extends AggResult with Transformable {
def significantTerms(name: String): SignificantTermsAggResult = SignificantTermsAggResult(name, agg(name))

// metric aggs
def avg(name: String): AvgAggResult = AvgAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble))
def avg(name: String): AvgAggResult = AvgAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble), agg(name).get("value_as_string").map(_.toString))

def extendedStats(name: String): ExtendedStatsAggResult =
ExtendedStatsAggResult(
Expand All @@ -257,9 +257,9 @@ trait HasAggregations extends AggResult with Transformable {
)

def cardinality(name: String): CardinalityAggResult = CardinalityAggResult(name, agg(name)("value").toString.toDouble)
def sum(name: String): SumAggResult = SumAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble))
def min(name: String): MinAggResult = MinAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble))
def max(name: String): MaxAggResult = MaxAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble))
def sum(name: String): SumAggResult = SumAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble), agg(name).get("value_as_string").map(_.toString))
def min(name: String): MinAggResult = MinAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble), agg(name).get("value_as_string").map(_.toString))
def max(name: String): MaxAggResult = MaxAggResult(name, Option(agg(name)("value")).map(_.toString.toDouble), agg(name).get("value_as_string").map(_.toString))

def percentiles(name: String): PercentilesAggResult = {
// can be keyed, so values can be either map or list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class MinMaxAggregationHttpTest extends AnyFreeSpec with DockerTests with Matche
createIndex("minmaxagg") mapping {
properties(
textField("name").fielddata(true),
intField("height").stored(true)
intField("height").stored(true),
dateField("opened").format("strict_date")
)
}
}.await
Expand All @@ -50,23 +51,25 @@ class MinMaxAggregationHttpTest extends AnyFreeSpec with DockerTests with Matche

client.execute(
bulk(
indexInto("minmaxagg") fields("name" -> "Willis Tower", "height" -> 1244),
indexInto("minmaxagg") fields("name" -> "Burj Kalifa", "height" -> 2456),
indexInto("minmaxagg") fields("name" -> "Tower of London", "height" -> 169),
indexInto("minmaxagg") fields("name" -> "Willis Tower", "height" -> 1244, "opened" -> "1973-09-01"),
indexInto("minmaxagg") fields("name" -> "Burj Kalifa", "height" -> 2456, "opened" -> "2010-01-04"),
indexInto("minmaxagg") fields("name" -> "Tower of London", "height" -> 169, "opened" -> "1285-01-01"),
indexInto("minmaxagg2") fields ("name" -> "building of unknown height")
).refresh(RefreshPolicy.Immediate)
).await

"max agg" - {
"should return the max for the context" in {
val resp = client.execute {
search("minmaxagg").matchAllQuery().aggs {
maxAgg("agg1", "height")
}
search("minmaxagg").matchAllQuery().aggs(
maxAgg("agg1", "height"),
maxAgg("opened", "opened"),
)
}.await.result
resp.totalHits shouldBe 3
val agg = resp.aggs.max("agg1")
agg.value shouldBe Some(2456)
resp.aggs.max("opened").valueAsString shouldBe Some("2010-01-04")
}
"should support results when matching docs do not define the field" in {
val resp = client.execute {
Expand All @@ -93,13 +96,15 @@ class MinMaxAggregationHttpTest extends AnyFreeSpec with DockerTests with Matche
"min agg" - {
"should return the max for the context" in {
val resp = client.execute {
search("minmaxagg").matchAllQuery().aggs {
minAgg("agg1", "height")
}
search("minmaxagg").matchAllQuery().aggs(
minAgg("agg1", "height"),
minAgg("opened", "opened")
)
}.await.result
resp.totalHits shouldBe 3
val agg = resp.aggs.min("agg1")
agg.value shouldBe Some(169)
resp.aggs.min("opened").valueAsString shouldBe Some("1285-01-01")
}
"should support results matching docs do not define the field" in {
val resp = client.execute {
Expand Down

0 comments on commit c908a28

Please sign in to comment.