Skip to content

Commit

Permalink
(dsl): Support 'terms' query (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
drmarjanovic authored Apr 26, 2023
1 parent 06dafa3 commit ea9183b
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 168 deletions.
6 changes: 6 additions & 0 deletions docs/overview/queries/elastic_query_terms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: elastic_query_terms
title: "Terms Query"
---

TBD
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,38 @@ object HttpExecutorSpec extends IntegrationSpec {
Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("search for a document using a terms query") {
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument, genDocumentId, genTestDocument) {
(firstDocumentId, firstDocument, secondDocumentId, secondDocument, thirdDocumentId, thirdDocument) =>
for {
_ <- Executor.execute(ElasticRequest.deleteByQuery(firstSearchIndex, matchAll))
firstDocumentUpdated = firstDocument.copy(stringField = s"this is ${firstDocument.stringField} test")
secondDocumentUpdated =
secondDocument.copy(stringField = s"this is ${secondDocument.stringField} another test")
_ <-
Executor.execute(
ElasticRequest
.bulk(
ElasticRequest.upsert[TestDocument](firstSearchIndex, firstDocumentId, firstDocumentUpdated),
ElasticRequest
.upsert[TestDocument](firstSearchIndex, secondDocumentId, secondDocumentUpdated),
ElasticRequest
.upsert[TestDocument](firstSearchIndex, thirdDocumentId, thirdDocument)
)
.refreshTrue
)
query = terms(
field = TestDocument.stringField,
values = firstDocument.stringField.toLowerCase,
secondDocument.stringField.toLowerCase
)
res <- Executor.execute(ElasticRequest.search(firstSearchIndex, query)).documentAs[TestDocument]
} yield assert(res)(hasSameElements(List(firstDocumentUpdated, secondDocumentUpdated)))
}
} @@ around(
Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("search for a document using nested query") {
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument) {
(firstDocumentId, firstDocument, secondDocumentId, secondDocument) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object ElasticQuery {
* @return
* an instance of [[zio.elasticsearch.query.WildcardQuery]] that represents the wildcard query to be performed.
*/
final def contains[S](field: Field[S, _], value: String): WildcardQuery[S] =
final def contains[S](field: Field[S, String], value: String): WildcardQuery[S] =
Wildcard(field = field.toString, value = s"*$value*", boost = None, caseInsensitive = None)

/**
Expand Down Expand Up @@ -340,7 +340,7 @@ object ElasticQuery {
* @return
* an instance of [[zio.elasticsearch.query.WildcardQuery]] that represents the wildcard query to be performed.
*/
final def startsWith[S](field: Field[S, _], value: String): WildcardQuery[S] =
final def startsWith[S](field: Field[S, String], value: String): WildcardQuery[S] =
Wildcard(field = field.toString, value = s"$value*", boost = None, caseInsensitive = None)

/**
Expand Down Expand Up @@ -369,31 +369,61 @@ object ElasticQuery {
* the value that will be used for the query, represented by an instance of type `A`
* @tparam S
* document for which field query is executed
* @tparam A
* the type of value that will be used for the query. A JSON decoder must be in scope for this type
* @return
* an instance of [[zio.elasticsearch.query.TermQuery]] that represents the term query to be performed.
*/
final def term[S, A: ElasticPrimitive](field: Field[S, A], value: A): TermQuery[S] =
final def term[S](field: Field[S, String], value: String): TermQuery[S] =
Term(field = field.toString, value = value, boost = None, caseInsensitive = None)

/**
* Constructs a type-safe instance of [[zio.elasticsearch.query.TermQuery]] using the specified parameters.
* Constructs an instance of [[zio.elasticsearch.query.TermQuery]] using the specified parameters.
* [[zio.elasticsearch.query.TermQuery]] is used for matching documents that contain an exact term in a provided
* field.
*
* @param field
* the field for which query is specified for
* @param value
* the value that will be used for the query, represented by an instance of type `A`
* @tparam A
* the type of value that will be used for the query. A JSON decoder must be in scope for this type
* @return
* an instance of [[zio.elasticsearch.query.TermQuery]] that represents the term query to be performed.
*/
final def term[A: ElasticPrimitive](field: String, value: A): Term[Any, A] =
final def term(field: String, value: String): Term[Any] =
Term(field = field, value = value, boost = None, caseInsensitive = None)

/**
* Constructs a type-safe instance of [[zio.elasticsearch.query.TermsQuery]] using the specified parameters.
* [[zio.elasticsearch.query.TermsQuery]] is used for matching documents that contain one or more term in a provided
* field. The terms query is the same as [[zio.elasticsearch.query.TermQuery]], except you can search for multiple
* values.
*
* @param field
* the type-safe field for which query is specified for
* @param values
* a list of terms that should be find in the provided field
* @tparam S
* document for which field query is executed
* @return
* an instance of [[zio.elasticsearch.query.TermsQuery]] that represents the term query to be performed.
*/
final def terms[S](field: Field[S, String], values: String*): Terms[S] =
Terms(field = field.toString, values = values.toList, boost = None)

/**
* Constructs an instance of [[zio.elasticsearch.query.TermsQuery]] using the specified parameters.
* [[zio.elasticsearch.query.TermsQuery]] is used for matching documents that contain one or more term in a provided
* field. The terms query is the same as [[zio.elasticsearch.query.TermQuery]], except you can search for multiple
* values.
*
* @param field
* the field for which query is specified for
* @param values
* a list of terms that should be find in the provided field
* @return
* an instance of [[zio.elasticsearch.query.TermsQuery]] that represents the term query to be performed.
*/
final def terms(field: String, values: String*): Terms[Any] =
Terms(field = field, values = values.toList, boost = None)

/**
* Constructs a type-safe instance of [[zio.elasticsearch.query.WildcardQuery]] using the specified parameters.
* [[zio.elasticsearch.query.WildcardQuery]] is used for matching documents containing a value that matches a provided
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,9 @@ private[elasticsearch] object Range {

sealed trait TermQuery[S] extends ElasticQuery[S] with HasBoost[TermQuery[S]] with HasCaseInsensitive[TermQuery[S]]

private[elasticsearch] final case class Term[S, A: ElasticPrimitive](
private[elasticsearch] final case class Term[S](
field: String,
value: A,
value: String,
boost: Option[Double],
caseInsensitive: Option[Boolean]
) extends TermQuery[S] { self =>
Expand All @@ -303,6 +303,23 @@ private[elasticsearch] final case class Term[S, A: ElasticPrimitive](
}
}

sealed trait TermsQuery[S] extends ElasticQuery[S] with HasBoost[TermsQuery[S]]

private[elasticsearch] final case class Terms[S](
field: String,
values: List[String],
boost: Option[Double]
) extends TermsQuery[S] { self =>
def boost(value: Double): TermsQuery[S] =
self.copy(boost = Some(value))

def paramsToJson(fieldPath: Option[String]): Json = {
val termsFields =
Some(fieldPath.foldRight(field)(_ + "." + _) -> Arr(values.map(Str(_)): _*)) ++ boost.map("boost" -> Num(_))
Obj("terms" -> Obj(termsFields.toList: _*))
}
}

sealed trait WildcardQuery[S]
extends ElasticQuery[S]
with HasBoost[WildcardQuery[S]]
Expand Down
Loading

0 comments on commit ea9183b

Please sign in to comment.