Skip to content

Commit

Permalink
(dsl): Support filter criteria in bool compound query (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevchuang authored Feb 7, 2023
1 parent 65ce729 commit 1e01903
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,23 @@ object ElasticQuery {

def wildcard(field: String, value: String): ElasticQuery[Wildcard] = WildcardQuery(field, value)

private[elasticsearch] final case class BoolQuery(must: List[ElasticQuery[_]], should: List[ElasticQuery[_]])
extends ElasticQuery[Bool] { self =>
private[elasticsearch] final case class BoolQuery(
filter: List[ElasticQuery[_]],
must: List[ElasticQuery[_]],
should: List[ElasticQuery[_]]
) extends ElasticQuery[Bool] { self =>

override def toJson: Json =
Obj("bool" -> Obj("must" -> Arr(must.map(_.toJson): _*), "should" -> Arr(should.map(_.toJson): _*)))
Obj(
"bool" -> Obj(
"filter" -> Arr(filter.map(_.toJson): _*),
"must" -> Arr(must.map(_.toJson): _*),
"should" -> Arr(should.map(_.toJson): _*)
)
)

def filter(queries: ElasticQuery[_]*): BoolQuery =
self.copy(filter = filter ++ queries)

def must(queries: ElasticQuery[_]*): BoolQuery =
self.copy(must = must ++ queries)
Expand All @@ -125,7 +137,7 @@ object ElasticQuery {
}

private[elasticsearch] object BoolQuery {
def empty: BoolQuery = BoolQuery(Nil, Nil)
def empty: BoolQuery = BoolQuery(Nil, Nil, Nil)
}

private[elasticsearch] final case class ExistsQuery private (field: String) extends ElasticQuery[Exists] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,34 @@ object QueryDSLSpec extends ZIOSpecDefault {

assert(query)(equalTo(MatchQuery(field = "name.keyword", value = "Name")))
},
test("successfully create `Filter` query from two Match queries") {
val query = boolQuery()
.filter(
matches(field = "day_of_week", value = "Monday"),
matches(field = "customer_gender", value = "MALE")
)

assert(query)(
equalTo(
BoolQuery(
filter = List(
MatchQuery(field = "day_of_week", value = "Monday"),
MatchQuery(field = "customer_gender", value = "MALE")
),
must = Nil,
should = Nil
)
)
)
},
test("successfully create `Must` query from two Match queries") {
val query = boolQuery()
.must(matches(field = "day_of_week", value = "Monday"), matches(field = "customer_gender", value = "MALE"))

assert(query)(
equalTo(
BoolQuery(
filter = Nil,
must = List(
MatchQuery(field = "day_of_week", value = "Monday"),
MatchQuery(field = "customer_gender", value = "MALE")
Expand All @@ -88,6 +109,7 @@ object QueryDSLSpec extends ZIOSpecDefault {
assert(query)(
equalTo(
BoolQuery(
filter = Nil,
must = Nil,
should = List(
MatchQuery(field = "day_of_week", value = "Monday"),
Expand All @@ -97,14 +119,38 @@ object QueryDSLSpec extends ZIOSpecDefault {
)
)
},
test("successfully create `Must/Should` mixed query") {
test("successfully create `Filter/Must/Should` mixed query with Filter containing two Match queries") {
val query = boolQuery()
.filter(
matches(field = "day_of_week", value = "Monday"),
matches(field = "customer_gender", value = "MALE")
)
.must(matches(field = "customer_age", value = 23))
.should(matches(field = "customer_id", value = 1))

assert(query)(
equalTo(
BoolQuery(
filter = List(
MatchQuery(field = "day_of_week", value = "Monday"),
MatchQuery(field = "customer_gender", value = "MALE")
),
must = List(MatchQuery(field = "customer_age", value = 23)),
should = List(MatchQuery(field = "customer_id", value = 1))
)
)
)
},
test("successfully create `Filter/Must/Should` mixed query with Must containing two Match queries") {
val query = boolQuery()
.filter(matches(field = "customer_id", value = 1))
.must(matches(field = "day_of_week", value = "Monday"), matches(field = "customer_gender", value = "MALE"))
.should(matches(field = "customer_age", value = 23))

assert(query)(
equalTo(
BoolQuery(
filter = List(MatchQuery(field = "customer_id", value = 1)),
must = List(
MatchQuery(field = "day_of_week", value = "Monday"),
MatchQuery(field = "customer_gender", value = "MALE")
Expand All @@ -114,8 +160,9 @@ object QueryDSLSpec extends ZIOSpecDefault {
)
)
},
test("successfully create `Should/Must` mixed query") {
test("successfully create `Filter/Must/Should` mixed query with Should containing two Match queries") {
val query = boolQuery()
.filter(matches(field = "customer_id", value = 1))
.must(matches(field = "customer_age", value = 23))
.should(
matches(field = "day_of_week", value = "Monday"),
Expand All @@ -125,6 +172,7 @@ object QueryDSLSpec extends ZIOSpecDefault {
assert(query)(
equalTo(
BoolQuery(
filter = List(MatchQuery(field = "customer_id", value = 1)),
must = List(MatchQuery(field = "customer_age", value = 23)),
should = List(
MatchQuery(field = "day_of_week", value = "Monday"),
Expand Down Expand Up @@ -373,13 +421,37 @@ object QueryDSLSpec extends ZIOSpecDefault {

assert(query.toJsonBody)(equalTo(expected.toJson))
},
test("properly encode Bool Query with Filter containing `Match` leaf query") {
val query = boolQuery().filter(matches(field = "day_of_week", value = "Monday"))
val expected =
"""
|{
| "query": {
| "bool": {
| "filter": [
| {
| "match": {
| "day_of_week": "Monday"
| }
| }
| ],
| "must": [],
| "should": []
| }
| }
|}
|""".stripMargin

assert(query.toJsonBody)(equalTo(expected.toJson))
},
test("properly encode Bool Query with Must containing `Match` leaf query") {
val query = boolQuery().must(matches(field = "day_of_week", value = "Monday"))
val expected =
"""
|{
| "query": {
| "bool": {
| "filter": [],
| "must": [
| {
| "match": {
Expand All @@ -402,6 +474,7 @@ object QueryDSLSpec extends ZIOSpecDefault {
|{
| "query": {
| "bool": {
| "filter": [],
| "must": [],
| "should": [
| {
Expand All @@ -417,15 +490,23 @@ object QueryDSLSpec extends ZIOSpecDefault {

assert(query.toJsonBody)(equalTo(expected.toJson))
},
test("properly encode Bool Query with both Must and Should containing `Match` leaf query") {
test("properly encode Bool Query with Filter, Must and Should containing `Match` leaf query") {
val query = boolQuery()
.filter(matches(field = "customer_age", value = 23))
.must(matches(field = "customer_id", value = 1))
.should(matches(field = "day_of_week", value = "Monday"))
val expected =
"""
|{
| "query": {
| "bool": {
| "filter": [
| {
| "match": {
| "customer_age": 23
| }
| }
| ],
| "must": [
| {
| "match": {
Expand Down

0 comments on commit 1e01903

Please sign in to comment.