Skip to content

Commit

Permalink
Range aggregation. Stats aggregation. Global aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
lynxpluto authored and ihostage committed Aug 1, 2023
1 parent 3e9ea53 commit e2a3ae3
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.taymyr.lagom.elasticsearch.search.dsl.query.aggregation

data class GlobalAggregation(
val aggs: Map<String, Aggregation>
) : Aggregation {
val global = mapOf<String, Any>() // Need to produce the global aggregation marker field "global": {}

class Builder {
private val aggs = mutableMapOf<String, Aggregation>()

fun agg(name: String, aggregation: Aggregation): Builder = apply { aggs[name] = aggregation }
fun build(): GlobalAggregation = GlobalAggregation(aggs)
}

companion object {
@JvmStatic
fun builder(): Builder = Builder()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.taymyr.lagom.elasticsearch.search.dsl.query.aggregation

import java.math.BigDecimal

data class RangeAggregation(
val range: RangeAggregationSpec,
val aggs: Map<String, Aggregation>? = null
) : Aggregation {

class Builder {
private var field = ""
private var keyed = false
private val ranges = mutableListOf<RangeSpec>()
private var stats = false
private val aggs = mutableMapOf<String, Aggregation>()

fun field(value: String): Builder = apply { field = value }
fun keyed(value: Boolean): Builder = apply { keyed = value }
fun range(from: BigDecimal? = null, to: BigDecimal? = null): Builder = apply {
ranges += RangeSpec(from, to)
}
fun range(from: Int? = null, to: Int? = null): Builder = apply {
ranges += RangeSpec(from?.toBigDecimal(), to?.toBigDecimal())
}
fun stats(): Builder = apply { stats = true }
fun agg(name: String, aggregation: Aggregation): Builder = apply { aggs[name] = aggregation }

fun build(): RangeAggregation {
if (field.isBlank()) error("'field' should not be blank")
if (stats) {
aggs[DEFAULT_STATS_AGG_NAME] = StatsAggregation(StatsAggregation.StatsFieldSpec(field))
}
return RangeAggregation(
RangeAggregationSpec(
field,
keyed,
if (ranges.isEmpty()) error("'ranges' should not be empty") else ranges
),
if (aggs.isEmpty()) null else aggs.toMap()
)
}
}

companion object {
const val DEFAULT_STATS_AGG_NAME = "agg_stats"

@JvmStatic
fun builder(): Builder = Builder()
}
}

data class RangeAggregationSpec(
val field: String,
val keyed: Boolean = false,
val ranges: List<RangeSpec>
)

data class RangeSpec(
val from: BigDecimal?,
val to: BigDecimal?
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.taymyr.lagom.elasticsearch.search.dsl.query.aggregation

import java.math.BigDecimal

data class StatsAggregation(
val stats: StatsFieldSpec,
val missing: BigDecimal? = null
) : Aggregation {
data class StatsFieldSpec(val field: String)

companion object {
@JvmStatic
@JvmOverloads
fun statsAggregation(field: String, missing: BigDecimal? = null) = StatsAggregation(StatsFieldSpec(field), missing)
}
}

data class StatsAggregationResult(
val count: Int,
val min: BigDecimal?,
val max: BigDecimal?,
val avg: BigDecimal?,
val sum: BigDecimal?
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import org.taymyr.lagom.elasticsearch.search.dsl.query.Order;
import org.taymyr.lagom.elasticsearch.search.dsl.query.term.IdsQuery;

import java.math.BigDecimal;

import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.taymyr.lagom.elasticsearch.Helpers.resourceAsString;
Expand Down Expand Up @@ -40,6 +42,24 @@ void shouldSuccessfullySerializeSearchRequestWithAggregation() {
.agg("agg2", TermsAggregation.builder().field("field2").build())
).build()
)
.agg(
"globalAggregation",
GlobalAggregation.builder()
.agg(
"rangeAggregation",
RangeAggregation.builder()
.field("price1")
.keyed(false)
.range(0, 100)
.stats()
.agg(
"price1StatsMissing",
StatsAggregation.statsAggregation("price1", BigDecimal.ZERO)
)
.build()
)
.build()
)
.build();
String actual = serializeRequest(request, SearchRequest.class);
String expected = resourceAsString("org/taymyr/lagom/elasticsearch/search/dsl/query/aggregation/request.json");
Expand Down Expand Up @@ -71,4 +91,4 @@ void shouldThrowExceptionForIncorrectAggregation() {
.isInstanceOf(IllegalStateException.class)
.hasMessage("Field 'aggs' can't be empty");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,33 @@
]
}
}
},
"globalAggregation": {
"global": {},
"aggs": {
"rangeAggregation": {
"range": {
"field": "price1",
"keyed": false,
"ranges": [
{ "from": 0, "to": 100 }
]
},
"aggs": {
"agg_stats": {
"stats": {
"field": "price1"
}
},
"price1StatsMissing": {
"stats": {
"field": "price1"
},
"missing": 0
}
}
}
}
}
},
"query": {
Expand All @@ -65,4 +92,4 @@
]
}
}
}
}

0 comments on commit e2a3ae3

Please sign in to comment.