From fb3c6d0c61bed4d224aabd8d7c0695ab795780a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Manciot?= Date: Sat, 22 Jun 2024 09:23:19 +0200 Subject: [PATCH] update bool query for filtered aggregate --- .../elastic/sql/ElasticQuery.scala | 6 +- .../app/softnetwork/elastic/sql/package.scala | 27 +-- .../elastic/sql/ElasticQuerySpec.scala | 194 +++++++++++++++++- 3 files changed, 205 insertions(+), 22 deletions(-) diff --git a/sql/src/main/scala/app/softnetwork/elastic/sql/ElasticQuery.scala b/sql/src/main/scala/app/softnetwork/elastic/sql/ElasticQuery.scala index a15c207..7b937be 100644 --- a/sql/src/main/scala/app/softnetwork/elastic/sql/ElasticQuery.scala +++ b/sql/src/main/scala/app/softnetwork/elastic/sql/ElasticQuery.scala @@ -146,12 +146,16 @@ object ElasticQuery { def _filtered: Aggregation = { aggregation.filter match { case Some(f) => + val boolQuery = Option(ElasticBoolQuery(group = true)) val filteredAgg = s"filtered_agg" aggPath ++= Seq(filteredAgg) filterAgg( filteredAgg, f.criteria - .map(_.asFilter(None).query(Set(identifier.innerHitsName).flatten, None)) + .map( + _.asFilter(boolQuery) + .query(Set(identifier.innerHitsName).flatten, boolQuery) + ) .getOrElse(matchAllQuery()) ) subaggs { aggPath ++= Seq(agg) diff --git a/sql/src/main/scala/app/softnetwork/elastic/sql/package.scala b/sql/src/main/scala/app/softnetwork/elastic/sql/package.scala index b5d89e3..975a7a0 100644 --- a/sql/src/main/scala/app/softnetwork/elastic/sql/package.scala +++ b/sql/src/main/scala/app/softnetwork/elastic/sql/package.scala @@ -681,22 +681,17 @@ package object sql { innerHitsNames: Set[String] = Set.empty, currentQuery: Option[ElasticBoolQuery] ): Query = { - criteria match { - case c: ElasticNested => - c.query(innerHitsNames, currentQuery) - case _ => - if (innerHitsNames.contains(innerHitsName.getOrElse(""))) { - criteria.asFilter(currentQuery).query(innerHitsNames, currentQuery) - } else { - val boolQuery = Option(ElasticBoolQuery(group = true)) - val filteredQuery = criteria.asFilter(boolQuery) - nestedQuery( - relationType.getOrElse(""), - filteredQuery - .query(innerHitsNames + innerHitsName.getOrElse(""), boolQuery) - ) /*.scoreMode(ScoreMode.None)*/ - .inner(innerHits(innerHitsName.getOrElse(""))) - } + if (innerHitsNames.contains(innerHitsName.getOrElse(""))) { + criteria.asFilter(currentQuery).query(innerHitsNames, currentQuery) + } else { + val boolQuery = Option(ElasticBoolQuery(group = true)) + nestedQuery( + relationType.getOrElse(""), + criteria + .asFilter(boolQuery) + .query(innerHitsNames + innerHitsName.getOrElse(""), boolQuery) + ) /*.scoreMode(ScoreMode.None)*/ + .inner(innerHits(innerHitsName.getOrElse(""))) } } } diff --git a/sql/src/test/scala/app/softnetwork/elastic/sql/ElasticQuerySpec.scala b/sql/src/test/scala/app/softnetwork/elastic/sql/ElasticQuerySpec.scala index 5c650d9..b548e80 100644 --- a/sql/src/test/scala/app/softnetwork/elastic/sql/ElasticQuerySpec.scala +++ b/sql/src/test/scala/app/softnetwork/elastic/sql/ElasticQuerySpec.scala @@ -485,7 +485,7 @@ class ElasticQuerySpec extends AnyFlatSpec with Matchers { select.isDefined shouldBe true val result = select.get result.query shouldBe - """ + """ |{ | "query":{ | "bool":{ @@ -502,7 +502,7 @@ class ElasticQuerySpec extends AnyFlatSpec with Matchers { |}""".stripMargin.replaceAll("\\s+", "") } - it should "handle complex query" in { + it should "perform complex query" in { val select = ElasticQuery.select( SQLQuery( s"""SELECT @@ -511,7 +511,7 @@ class ElasticQuerySpec extends AnyFlatSpec with Matchers { | stores-dev store, | UNNEST(store.products) as inner_products |WHERE - | ( + | (( | firstName is not null AND | lastName is not null AND | description is not null AND @@ -529,7 +529,7 @@ class ElasticQuerySpec extends AnyFlatSpec with Matchers { | inner_products.deleted=false AND | inner_products.upForSale=true AND | inner_products.stock > 0 - | ) AND + | )) AND | ( | match(products.name, "lasagnes") OR | match(products.description, "lasagnes") OR @@ -540,7 +540,191 @@ class ElasticQuerySpec extends AnyFlatSpec with Matchers { ) select.isDefined shouldBe true val result = select.get - println(result.query) +// println(result.query) + result.query shouldBe + """ + |{ + | "query":{ + | "bool":{ + | "filter":[ + | { + | "bool":{ + | "filter":[ + | { + | "bool":{ + | "filter":[ + | { + | "bool":{ + | "filter":[ + | { + | "bool":{ + | "filter":[ + | { + | "bool":{ + | "filter":[ + | { + | "exists":{ + | "field":"firstName" + | } + | }, + | { + | "exists":{ + | "field":"lastName" + | } + | },{ + | "exists":{ + | "field":"description" + | } + | },{ + | "range":{ + | "preparationTime":{ + | "lte":"120" + | } + | } + | } + | ] + | } + | }, + | { + | "term":{ + | "deliveryPeriods.dayOfWeek":{ + | "value":"6" + | } + | } + | } + | ] + | } + | }, + | { + | "bool":{ + | "should":[ + | { + | "geo_distance":{ + | "distance":"7000m", + | "pickup.location":[0.0,0.0] + | } + | }, + | { + | "geo_distance":{ + | "distance":"7000m", + | "withdrawals.location":[0.0,0.0] + | } + | } + | ] + | } + | } + | ] + | } + | }, + | { + | "bool":{ + | "must_not":[ + | { + | "term":{ + | "receiptOfOrdersDisabled":{ + | "value":true + | } + | } + | } + | ], + | "filter":[ + | { + | "bool":{ + | "must_not":[ + | { + | "regexp":{ + | "blockedCustomers":{ + | "value":"()uuid()" + | } + | } + | } + | ] + | } + | } + | ] + | } + | } + | ] + | } + | }, + | { + | "nested":{ + | "path":"products", + | "query":{ + | "bool":{ + | "filter":[ + | { + | "term":{ + | "products.deleted":{ + | "value":false + | } + | } + | }, + | { + | "term":{ + | "products.upForSale":{ + | "value":true + | } + | } + | }, + | { + | "range":{ + | "products.stock":{ + | "gt":"0" + | } + | } + | } + | ] + | } + | }, + | "inner_hits":{ + | "name":"inner_products" + | } + | } + | } + | ] + | } + | }, + | { + | "bool":{ + | "should":[ + | { + | "match":{ + | "products.name":{ + | "query":"lasagnes" + | } + | } + | }, + | { + | "match":{ + | "products.description":{ + | "query":"lasagnes" + | } + | } + | }, + | { + | "match":{ + | "products.ingredients":{ + | "query":"lasagnes" + | } + | } + | } + | ] + | } + | } + | ] + | } + | }, + | "from":0, + | "size":100, + | "_source":{ + | "includes":[ + | "inner_products.name", + | "inner_products.category", + | "inner_products.price" + | ] + | } + |}""".stripMargin.replaceAll("\\s+", "") } }