Skip to content

Commit

Permalink
refactoring of sql package
Browse files Browse the repository at this point in the history
  • Loading branch information
fupelaqu committed Jun 26, 2024
1 parent 79a6b4b commit 25aa486
Show file tree
Hide file tree
Showing 16 changed files with 1,102 additions and 1,051 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package app.softnetwork.elastic.sql

import com.sksamuel.elastic4s.searches.aggs.Aggregation

case class ElasticAggregation(
aggName: String,
field: String,
sourceField: String,
sources: Seq[String] = Seq.empty,
query: Option[String] = None,
distinct: Boolean = false,
nested: Boolean = false,
filtered: Boolean = false,
aggType: AggregateFunction,
agg: Aggregation
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package app.softnetwork.elastic.sql

import com.sksamuel.elastic4s.http.search.MultiSearchBuilderFn
import com.sksamuel.elastic4s.searches.MultiSearchRequest

case class ElasticMultiSearchRequest(
requests: Seq[ElasticSearchRequest],
multiSearch: MultiSearchRequest
) {
def query: String = MultiSearchBuilderFn(multiSearch).replace("\"version\":true,", "") /*FIXME*/
}
44 changes: 3 additions & 41 deletions sql/src/main/scala/app/softnetwork/elastic/sql/ElasticQuery.scala
Original file line number Diff line number Diff line change
@@ -1,49 +1,11 @@
package app.softnetwork.elastic.sql

import com.sksamuel.elastic4s.http.search.{MultiSearchBuilderFn, SearchBodyBuilderFn}
import com.sksamuel.elastic4s.searches.{MultiSearchRequest, SearchRequest}
import com.sksamuel.elastic4s.searches.aggs.Aggregation

/** Created by smanciot on 27/06/2018.
*/
object ElasticQuery {}
object ElasticQuery {
def search(request: SearchRequest): SQLSearchRequest = ???

case class ElasticAggregation(
aggName: String,
field: String,
sourceField: String,
sources: Seq[String] = Seq.empty,
query: Option[String] = None,
distinct: Boolean = false,
nested: Boolean = false,
filtered: Boolean = false,
aggType: AggregateFunction,
agg: Aggregation
)

case class ElasticSearchRequest(
fields: Seq[SQLField],
except: Option[SQLExcept],
sources: Seq[String],
criteria: Option[SQLCriteria],
limit: Option[Int],
search: SearchRequest,
aggregations: Seq[ElasticAggregation] = Seq.empty
) {
def minScore(score: Option[Double]): ElasticSearchRequest = {
score match {
case Some(s) => this.copy(search = search minScore s)
case _ => this
}
}

def query: String =
SearchBodyBuilderFn(search).string().replace("\"version\":true,", "") /*FIXME*/
}

case class ElasticMultiSearchRequest(
requests: Seq[ElasticSearchRequest],
multiSearch: MultiSearchRequest
) {
def query: String = MultiSearchBuilderFn(multiSearch).replace("\"version\":true,", "") /*FIXME*/
def multiSearch(request: MultiSearchRequest): SQLMultiSearchRequest = ???
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package app.softnetwork.elastic.sql

import com.sksamuel.elastic4s.http.search.SearchBodyBuilderFn
import com.sksamuel.elastic4s.searches.SearchRequest

case class ElasticSearchRequest(
fields: Seq[SQLField],
except: Option[SQLExcept],
sources: Seq[String],
criteria: Option[SQLCriteria],
limit: Option[Int],
search: SearchRequest,
aggregations: Seq[ElasticAggregation] = Seq.empty
) {
def minScore(score: Option[Double]): ElasticSearchRequest = {
score match {
case Some(s) => this.copy(search = search minScore s)
case _ => this
}
}

def query: String =
SearchBodyBuilderFn(search).string().replace("\"version\":true,", "") /*FIXME*/
}
10 changes: 10 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLDelimiter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.softnetwork.elastic.sql

sealed trait SQLDelimiter extends SQLToken

sealed trait StartDelimiter extends SQLDelimiter
case object StartPredicate extends SQLExpr("(") with StartDelimiter

sealed trait EndDelimiter extends SQLDelimiter
case object EndPredicate extends SQLExpr(")") with EndDelimiter
case object Separator extends SQLExpr(",") with EndDelimiter
72 changes: 72 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLFrom.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package app.softnetwork.elastic.sql

case object FROM extends SQLExpr("from")

sealed trait SQLSource extends Updateable {
def update(request: SQLSearchRequest): SQLSource
}

case class SQLIdentifier(
columnName: String,
alias: Option[String] = None,
distinct: Option[String] = None,
nested: Boolean = false,
limit: Option[SQLLimit] = None
) extends SQLExpr({
var parts: Seq[String] = columnName.split("\\.").toSeq
alias match {
case Some(a) => parts = a +: parts
case _ =>
}
s"${distinct.getOrElse("")} ${parts.mkString(".")}".trim
})
with SQLSource {

lazy val nestedType: Option[String] = if (nested) Some(columnName.split('.').head) else None

lazy val innerHitsName: Option[String] = if (nested) alias else None

def update(request: SQLSearchRequest): SQLIdentifier = {
val parts: Seq[String] = columnName.split("\\.").toSeq
if (request.aliases.contains(parts.head)) {
request.unnests.find(_._1 == parts.head) match {
case Some(tuple) =>
this.copy(
alias = Some(parts.head),
columnName = s"${tuple._2}.${parts.tail.mkString(".")}",
nested = true,
limit = tuple._3
)
case _ =>
this.copy(
alias = Some(parts.head),
columnName = parts.tail.mkString(".")
)
}
} else {
this
}
}
}

case class SQLUnnest(identifier: SQLIdentifier, limit: Option[SQLLimit]) extends SQLSource {
override def sql: String = s"unnest(${identifier /*.copy(distinct = None)*/ .sql})"
def update(request: SQLSearchRequest): SQLUnnest =
this.copy(identifier = identifier.update(request))
}

case class SQLTable(source: SQLSource, alias: Option[SQLAlias] = None) extends Updateable {
override def sql: String = s"$source${asString(alias)}"
def update(request: SQLSearchRequest): SQLTable = this.copy(source = source.update(request))
}

case class SQLFrom(tables: Seq[SQLTable]) extends Updateable {
override def sql: String = s" $FROM ${tables.map(_.sql).mkString(",")}"
lazy val aliases: Seq[String] = tables.flatMap((table: SQLTable) => table.alias).map(_.alias)
lazy val unnests: Seq[(String, String, Option[SQLLimit])] = tables.collect {
case SQLTable(u: SQLUnnest, a) =>
(a.map(_.alias).getOrElse(u.identifier.columnName), u.identifier.columnName, u.limit)
}
def update(request: SQLSearchRequest): SQLFrom =
this.copy(tables = tables.map(_.update(request)))
}
12 changes: 12 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLFunction.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.softnetwork.elastic.sql

sealed trait SQLFunction extends SQLToken

sealed trait AggregateFunction extends SQLFunction
case object Count extends SQLExpr("count") with AggregateFunction
case object Min extends SQLExpr("min") with AggregateFunction
case object Max extends SQLExpr("max") with AggregateFunction
case object Avg extends SQLExpr("avg") with AggregateFunction
case object Sum extends SQLExpr("sum") with AggregateFunction

case object SQLDistance extends SQLExpr("distance") with SQLFunction with SQLOperator
5 changes: 5 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLLimit.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package app.softnetwork.elastic.sql

case object LIMIT extends SQLExpr("limit")

case class SQLLimit(limit: Int) extends SQLExpr(s"limit $limit")
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package app.softnetwork.elastic.sql

import com.sksamuel.elastic4s.searches.MultiSearchRequest

case class SQLMultiSearchRequest(requests: Seq[SQLSearchRequest]) extends SQLToken {
override def sql: String = s"${requests.map(_.sql).mkString(" union ")}"

def update(): SQLMultiSearchRequest = this.copy(requests = requests.map(_.update()))

lazy val multiSearchRequest: MultiSearchRequest = MultiSearchRequest(
requests.map(_.searchRequest)
)
}
36 changes: 36 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLOperator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package app.softnetwork.elastic.sql

trait SQLOperator extends SQLToken

sealed trait SQLExpressionOperator extends SQLOperator

sealed trait SQLComparisonOperator extends SQLExpressionOperator

case object EQ extends SQLExpr("=") with SQLComparisonOperator
case object NE extends SQLExpr("<>") with SQLComparisonOperator
case object GE extends SQLExpr(">=") with SQLComparisonOperator
case object GT extends SQLExpr(">") with SQLComparisonOperator
case object LE extends SQLExpr("<=") with SQLComparisonOperator
case object LT extends SQLExpr("<") with SQLComparisonOperator

sealed trait SQLLogicalOperator extends SQLExpressionOperator

case object IN extends SQLExpr("in") with SQLLogicalOperator
case object LIKE extends SQLExpr("like") with SQLLogicalOperator
case object BETWEEN extends SQLExpr("between") with SQLLogicalOperator
case object IS_NULL extends SQLExpr("is null") with SQLLogicalOperator
case object IS_NOT_NULL extends SQLExpr("is not null") with SQLLogicalOperator
case object NOT extends SQLLogicalOperator { override val sql: String = "not" }

sealed trait SQLPredicateOperator extends SQLLogicalOperator

case object AND extends SQLPredicateOperator { override val sql: String = "and" }
case object OR extends SQLPredicateOperator { override val sql: String = "or" }

case object UNION extends SQLExpr("union") with SQLOperator

sealed trait ElasticOperator extends SQLOperator
case object NESTED extends SQLExpr("nested") with ElasticOperator
case object CHILD extends SQLExpr("child") with ElasticOperator
case object PARENT extends SQLExpr("parent") with ElasticOperator
case object MATCH extends SQLExpr("match") with ElasticOperator
17 changes: 17 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLOrderBy.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package app.softnetwork.elastic.sql

case object ORDER_BY extends SQLExpr("order by")

sealed trait SortOrder extends SQLToken

case object DESC extends SQLExpr("desc") with SortOrder

case object ASC extends SQLExpr("asc") with SortOrder

case class SQLFieldSort(field: String, order: Option[SortOrder]) extends SQLToken {
override def sql: String = s"$field ${order.getOrElse(ASC).sql}"
}

case class SQLOrderBy(sorts: Seq[SQLFieldSort]) extends SQLToken {
override def sql: String = s" $ORDER_BY ${sorts.map(_.sql).mkString(",")}"
}
70 changes: 70 additions & 0 deletions sql/src/main/scala/app/softnetwork/elastic/sql/SQLQuery.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package app.softnetwork.elastic.sql

import com.sksamuel.elastic4s.ElasticApi
import com.sksamuel.elastic4s.http.search.SearchBodyBuilderFn

case class SQLQuery(query: String, score: Option[Double] = None) {
import SQLImplicits._

lazy val select: Option[Either[ElasticSearchRequest, ElasticMultiSearchRequest]] = {
val select: Option[Either[SQLSearchRequest, SQLMultiSearchRequest]] = query
select map {
case Left(s) => Left(s)
case Right(m) =>
Right(ElasticMultiSearchRequest(m.requests.map(_.asInstanceOf), m.multiSearchRequest))
}
}

lazy val aggregations: Seq[ElasticAggregation] = {
import com.sksamuel.elastic4s.ElasticApi._
val select: Option[Either[SQLSearchRequest, SQLMultiSearchRequest]] = this.query
select
.map {
case Left(l) =>
l.aggregations.map(aggregation => {

val queryFiltered = l.where.map(_.asQuery()).getOrElse(matchAllQuery)

aggregation.copy(
sources = l.sources,
query = Some(
(aggregation.aggType match {
case Count if aggregation.sourceField.equalsIgnoreCase("_id") =>
SearchBodyBuilderFn(
ElasticApi.search("") query {
queryFiltered
}
)
case _ =>
SearchBodyBuilderFn(
ElasticApi.search("") query {
queryFiltered
}
aggregations {
aggregation.agg
}
size 0
)
}).string().replace("\"version\":true,", "") /*FIXME*/
)
)
})

case _ => Seq.empty

}
.getOrElse(Seq.empty)
}

lazy val search: Option[ElasticSearchRequest] = select match {
case Some(Left(value)) => Some(value.minScore(score))
case _ => None
}

lazy val multiSearch: Option[ElasticMultiSearchRequest] = select match {
case Some(Right(value)) => Some(value)
case _ => None
}

def minScore(score: Double): SQLQuery = this.copy(score = Some(score))
}
Loading

0 comments on commit 25aa486

Please sign in to comment.