Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Size and Order parameters to Terms aggregation #192

Merged
merged 8 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ object ElasticAggregation {
* performed.
*/
final def termsAggregation(name: String, field: Field[_, String]): TermsAggregation =
Terms(name = name, field = field.toString, subAggregations = Nil)
Terms(name = name, field = field.toString, order = Set.empty, subAggregations = Nil, size = None)

/**
* Constructs an instance of [[zio.elasticsearch.aggregation.TermsAggregation]] using the specified parameters.
Expand All @@ -56,5 +56,5 @@ object ElasticAggregation {
* performed.
*/
final def termsAggregation(name: String, field: String): TermsAggregation =
Terms(name = name, field = field, subAggregations = Nil)
Terms(name = name, field = field, order = Set.empty, subAggregations = Nil, size = None)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2022 LambdaWorks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package zio.elasticsearch.aggregation

import zio.elasticsearch.query.sort.SortOrder

final case class AggregationOrder(value: String, order: SortOrder)
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import zio.elasticsearch.ElasticAggregation.multipleAggregations
import zio.elasticsearch.ElasticPrimitive.ElasticPrimitiveOps
import zio.elasticsearch.aggregation.options._
import zio.json.ast.Json
import zio.json.ast.Json.Obj
import zio.json.ast.Json.{Arr, Obj}

sealed trait ElasticAggregation { self =>
def paramsToJson: Json
private[elasticsearch] def paramsToJson: Json

final def toJson: Json =
private[elasticsearch] final def toJson: Json =
Obj("aggs" -> paramsToJson)
}

Expand All @@ -41,44 +41,73 @@ private[elasticsearch] final case class Multiple(aggregations: List[SingleElasti
self.copy(aggregations = self.aggregations ++ aggregations)

def paramsToJson: Json =
Obj(aggregations.map { case Terms(name, field, subAggregations) =>
(
name,
Obj(("terms" -> Obj("field" -> field.toJson)) :: subAggregations.map { agg =>
"aggs" -> agg.paramsToJson
}: _*)
)
}: _*)
aggregations.map(_.paramsToJson).reduce(_ merge _)

def withAgg(agg: SingleElasticAggregation): MultipleAggregations =
self.copy(aggregations = agg +: aggregations)
}

sealed trait TermsAggregation extends SingleElasticAggregation with WithSubAgg[TermsAggregation] with WithAgg
sealed trait TermsAggregation
extends SingleElasticAggregation
with HasOrder[TermsAggregation]
with WithSubAgg[TermsAggregation]
with WithAgg {

/**
* Sets the maximum number of terms to be returned by the aggregation. By default, the [[TermsAggregation]] returns
* the top ten terms with the most documents.
*
* @param value
* a non-negative number to set the `size` parameter in the [[zio.elasticsearch.aggregation.TermsAggregation]]
* @return
* an instance of the [[zio.elasticsearch.aggregation.TermsAggregation]] enriched with the `size` parameter.
*/
def size(value: Int): TermsAggregation
}

private[elasticsearch] final case class Terms(
name: String,
field: String,
subAggregations: List[SingleElasticAggregation]
order: Set[AggregationOrder],
subAggregations: List[SingleElasticAggregation],
size: Option[Int]
) extends TermsAggregation { self =>
def orderBy(order: AggregationOrder, orders: AggregationOrder*): TermsAggregation =
self.copy(order = self.order + order ++ orders.toSet)

def paramsToJson: Json =
Obj(name -> paramsToJsonHelper(field, subAggregations))
Obj(name -> paramsToJsonHelper)

def size(value: Int): TermsAggregation =
self.copy(size = Some(value))

def withAgg(aggregation: SingleElasticAggregation): MultipleAggregations =
multipleAggregations.aggregations(self, aggregation)

def withSubAgg(aggregation: SingleElasticAggregation): TermsAggregation =
self.copy(subAggregations = aggregation +: subAggregations)

private def paramsToJsonHelper(currField: String, currSubAggs: List[SingleElasticAggregation]): Obj =
if (currSubAggs.nonEmpty) {
Obj(
"terms" -> Obj("field" -> currField.toJson),
"aggs" -> Obj(currSubAggs.map { case termsAgg: Terms =>
(termsAgg.name, paramsToJsonHelper(termsAgg.field, termsAgg.subAggregations))
}: _*)
)
} else {
Obj("terms" -> Obj("field" -> currField.toJson))
}
private def paramsToJsonHelper: Obj = {
val orderJson: Json =
order.toList match {
case Nil =>
Obj()
case o :: Nil =>
Obj("order" -> Obj(o.value -> o.order.toString.toJson))
case orders =>
Obj("order" -> Arr(orders.collect { case AggregationOrder(value, order) =>
Obj(value -> order.toString.toJson)
}: _*))
}

val sizeJson = size.fold(Obj())(s => Obj("size" -> s.toJson))

val subAggsJson =
if (self.subAggregations.nonEmpty)
dbulaja98 marked this conversation as resolved.
Show resolved Hide resolved
Obj("aggs" -> self.subAggregations.map(_.paramsToJson).reduce(_ merge _))
else
Obj()

Obj("terms" -> (Obj("field" -> self.field.toJson) merge orderJson merge sizeJson)) merge subAggsJson
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2022 LambdaWorks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package zio.elasticsearch.aggregation.options

import zio.elasticsearch.aggregation.AggregationOrder
import zio.elasticsearch.query.sort.SortOrder.{Asc, Desc}

private[elasticsearch] trait HasOrder[A <: HasOrder[A]] {

/**
* Sets the `order` parameter for the [[zio.elasticsearch.aggregation.ElasticAggregation]]. At least one
* [[zio.elasticsearch.aggregation.AggregationOrder]] must be specified.
*
* @param order
* the required [[zio.elasticsearch.aggregation.AggregationOrder]] object defining the sort order for the
* aggregation results
* @param orders
* a list of [[zio.elasticsearch.aggregation.AggregationOrder]] defining the sort order for the aggregation results
* @return
* an instance of the [[zio.elasticsearch.aggregation.ElasticAggregation]] enriched with the `order` parameter.
*/
def orderBy(order: AggregationOrder, orders: AggregationOrder*): A

/**
* Sets the `order` parameter for the [[zio.elasticsearch.aggregation.ElasticAggregation]] using the `_count` field in
* ascending order.
*
* @return
* an instance of the [[zio.elasticsearch.aggregation.ElasticAggregation]] enriched with the `order` parameter.
*/
final def orderByCountAsc: A =
orderBy(AggregationOrder("_count", Asc))

/**
* Sets the `order` parameter for the [[zio.elasticsearch.aggregation.ElasticAggregation]] using the `_count` field in
* descending order.
*
* @return
* an instance of the [[zio.elasticsearch.aggregation.ElasticAggregation]] enriched with the `order` parameter.
*/
final def orderByCountDesc: A =
orderBy(AggregationOrder("_count", Desc))

/**
* Sets the `order` parameter for the [[zio.elasticsearch.aggregation.ElasticAggregation]] using the `_key` field in
* ascending order.
*
* @return
* an instance of the [[zio.elasticsearch.aggregation.ElasticAggregation]] enriched with the `order` parameter.
*/
final def orderByKeyAsc: A =
orderBy(AggregationOrder("_key", Asc))

/**
* Sets the `order` parameter for the [[zio.elasticsearch.aggregation.ElasticAggregation]] using the `_key` field in
* descending order.
*
* @return
* an instance of the [[zio.elasticsearch.aggregation.ElasticAggregation]] enriched with the `order` parameter.
*/
final def orderByKeyDesc: A =
orderBy(AggregationOrder("_key", Desc))
}
Loading