Skip to content

Commit afda884

Browse files
authored
Merge pull request #14 from SOFTNETWORK-APP/feature/orderByWithAggsAndBuckets
having and order by with aggregates and buckets
2 parents d7f736e + 353e0fc commit afda884

File tree

17 files changed

+1041
-359
lines changed

17 files changed

+1041
-359
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ThisBuild / organization := "app.softnetwork"
1919

2020
name := "softclient4es"
2121

22-
ThisBuild / version := "0.3.0"
22+
ThisBuild / version := "0.4.0"
2323

2424
ThisBuild / scalaVersion := scala213
2525

es6/sql-bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticAggregation.scala

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@ package app.softnetwork.elastic.sql.bridge
22

33
import app.softnetwork.elastic.sql.{
44
AggregateFunction,
5+
Asc,
56
Avg,
7+
BucketSelectorScript,
68
Count,
79
ElasticBoolQuery,
810
Max,
911
Min,
1012
SQLBucket,
1113
SQLCriteria,
1214
SQLField,
15+
SortOrder,
1316
Sum
1417
}
1518
import com.sksamuel.elastic4s.ElasticApi.{
1619
avgAgg,
20+
bucketSelectorAggregation,
1721
cardinalityAgg,
1822
filterAgg,
1923
maxAgg,
@@ -23,11 +27,13 @@ import com.sksamuel.elastic4s.ElasticApi.{
2327
termsAgg,
2428
valueCountAgg
2529
}
30+
import com.sksamuel.elastic4s.script.Script
2631
import com.sksamuel.elastic4s.searches.aggs.{
2732
Aggregation,
2833
FilterAggregation,
2934
NestedAggregation,
30-
TermsAggregation
35+
TermsAggregation,
36+
TermsOrder
3137
}
3238

3339
import scala.language.implicitConversions
@@ -42,17 +48,24 @@ case class ElasticAggregation(
4248
nestedAgg: Option[NestedAggregation] = None,
4349
filteredAgg: Option[FilterAggregation] = None,
4450
aggType: AggregateFunction,
45-
agg: Aggregation
51+
agg: Aggregation,
52+
direction: Option[SortOrder] = None
4653
) {
4754
val nested: Boolean = nestedAgg.nonEmpty
4855
val filtered: Boolean = filteredAgg.nonEmpty
4956
}
5057

5158
object ElasticAggregation {
52-
def apply(sqlAgg: SQLField, filter: Option[SQLCriteria]): ElasticAggregation = {
59+
def apply(
60+
sqlAgg: SQLField,
61+
having: Option[SQLCriteria],
62+
bucketsDirection: Map[String, SortOrder]
63+
): ElasticAggregation = {
5364
import sqlAgg._
5465
val sourceField = identifier.name
5566

67+
val direction = bucketsDirection.get(identifier.identifierName)
68+
5669
val field = fieldAlias match {
5770
case Some(alias) => alias.alias
5871
case _ => sourceField
@@ -92,7 +105,7 @@ object ElasticAggregation {
92105
val filteredAggName = "filtered_agg"
93106

94107
val filteredAgg: Option[FilterAggregation] =
95-
filter match {
108+
having match {
96109
case Some(f) =>
97110
val boolQuery = Option(ElasticBoolQuery(group = true))
98111
Some(
@@ -135,44 +148,60 @@ object ElasticAggregation {
135148
nestedAgg = nestedAgg,
136149
filteredAgg = filteredAgg,
137150
aggType = aggType,
138-
agg = _agg
151+
agg = _agg,
152+
direction = direction
139153
)
140154
}
141155

142-
/*
143-
def apply(
156+
def buildBuckets(
144157
buckets: Seq[SQLBucket],
158+
bucketsDirection: Map[String, SortOrder],
145159
aggregations: Seq[Aggregation],
146-
current: Option[TermsAggregation]
160+
aggregationsDirection: Map[String, SortOrder],
161+
having: Option[SQLCriteria]
147162
): Option[TermsAggregation] = {
148-
buckets match {
149-
case Nil =>
150-
current.map(_.copy(subaggs = aggregations))
151-
case bucket +: tail =>
152-
val agg = termsAgg(bucket.name, s"${bucket.identifier.name}.keyword")
153-
current match {
154-
case Some(a) =>
155-
apply(tail, aggregations, Some(agg)) match {
156-
case Some(subAgg) =>
157-
Some(a.copy(subaggs = a.subaggs :+ subAgg))
158-
case _ => Some(a)
159-
}
163+
Console.println(bucketsDirection)
164+
buckets.reverse.foldLeft(Option.empty[TermsAggregation]) { (current, bucket) =>
165+
val agg = {
166+
bucketsDirection.get(bucket.identifier.identifierName) match {
167+
case Some(direction) =>
168+
termsAgg(bucket.name, s"${bucket.identifier.name}.keyword")
169+
.order(Seq(direction match {
170+
case Asc => TermsOrder(bucket.name, asc = true)
171+
case _ => TermsOrder(bucket.name, asc = false)
172+
}))
160173
case None =>
161-
apply(tail, aggregations, Some(agg))
174+
termsAgg(bucket.name, s"${bucket.identifier.name}.keyword")
162175
}
163-
}
164-
}
165-
*/
166-
167-
def buildBuckets(
168-
buckets: Seq[SQLBucket],
169-
aggregations: Seq[Aggregation]
170-
): Option[TermsAggregation] = {
171-
buckets.reverse.foldLeft(Option.empty[TermsAggregation]) { (current, bucket) =>
172-
val agg = termsAgg(bucket.name, s"${bucket.identifier.name}.keyword")
176+
}
173177
current match {
174178
case Some(subAgg) => Some(agg.copy(subaggs = Seq(subAgg)))
175-
case None => Some(agg.copy(subaggs = aggregations))
179+
case None =>
180+
val aggregationsWithOrder: Seq[TermsOrder] = aggregationsDirection.toSeq.map { kv =>
181+
kv._2 match {
182+
case Asc => TermsOrder(kv._1, asc = true)
183+
case _ => TermsOrder(kv._1, asc = false)
184+
}
185+
}
186+
val withAggregationOrders =
187+
if (aggregationsWithOrder.nonEmpty)
188+
agg.order(aggregationsWithOrder)
189+
else
190+
agg
191+
val withHaving = having match {
192+
case Some(criteria) =>
193+
import BucketSelectorScript._
194+
val script = toPainless(criteria)
195+
val bucketsPath = extractBucketsPath(criteria)
196+
197+
val bucketSelector =
198+
bucketSelectorAggregation("having_filter", Script(script), bucketsPath)
199+
200+
withAggregationOrders.copy(subaggs = aggregations :+ bucketSelector)
201+
202+
case None => withAggregationOrders.copy(subaggs = aggregations)
203+
}
204+
Some(withHaving)
176205
}
177206
}
178207
}

es6/sql-bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticQuery.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ case class ElasticQuery(filter: ElasticFilter) {
6464
case isNull: SQLIsNull => isNull
6565
case isNotNull: SQLIsNotNull => isNotNull
6666
case in: SQLIn[_, _] => in
67-
case between: SQLBetween => between
67+
case between: SQLBetween[String] => between
68+
case between: SQLBetween[Long] => between
69+
case between: SQLBetween[Double] => between
6870
case geoDistance: ElasticGeoDistance => geoDistance
6971
case matchExpression: ElasticMatch => matchExpression
7072
case other =>

0 commit comments

Comments
 (0)