Skip to content

Commit

Permalink
(dsl): Support constantScore query (#307)
Browse files Browse the repository at this point in the history
  • Loading branch information
milicns authored Aug 29, 2023
1 parent d2e088b commit 8b3d2fd
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 0 deletions.
30 changes: 30 additions & 0 deletions docs/overview/queries/elastic_query_constant_score.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
id: elastic_query_constant_score
title: "Constant Score Query"
---

The `ConstantScore` query wraps a filter query and returns every matching document with a relevance score equal to the boost parameter value.

In order to use the `ConstantScore` query import the following:
```scala
import zio.elasticsearch.query.ConstantScoreQuery
import zio.elasticsearch.ElasticQuery._
```

You can create a `ConstantScore` query with arbitrary query(`MatchPhrase` in this example) using the `constantScore` method in the following manner:
```scala
val query: ConstantScoreQuery = constantScore(matchPhrase(field = "name", value = "test"))
```

You can create a [type-safe](https://lambdaworks.github.io/zio-elasticsearch/overview/overview_zio_prelude_schema) `ConstantScore` query with arbitrary [type-safe](https://lambdaworks.github.io/zio-elasticsearch/overview/overview_zio_prelude_schema) query(`MatchPhrase` in this example) using the `constantScore` method in the following manner:
```scala
val query: ConstantScoreQuery = constantScore(matchPhrase(field = Document.name, value = "test"))
```

If you want to change the `boost`, you can use `boost` method:
```scala
val queryWithBoost: ConstantScoreQuery = constantScore(matchPhrase(field = Document.name, value = "test")).boost(2.2)
```

You can find more information about `ConstantScore` query [here](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-constant-score-query.html).

Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,32 @@ object HttpExecutorSpec extends IntegrationSpec {
)
),
suite("searching for documents")(
test("search for a document using a constant score query") {
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument) {
(firstDocumentId, firstDocument, secondDocumentId, secondDocument) =>
for {
_ <- Executor.execute(ElasticRequest.deleteByQuery(firstSearchIndex, matchAll))
document = firstDocument.copy(stringField = "this is a test")
_ <-
Executor.execute(ElasticRequest.upsert[TestDocument](firstSearchIndex, firstDocumentId, document))
_ <- Executor.execute(
ElasticRequest
.upsert[TestDocument](firstSearchIndex, secondDocumentId, secondDocument)
.refreshTrue
)
query = constantScore(
matchPhrase(
field = TestDocument.stringField,
value = "test"
)
).boost(2.1)
res <- Executor.execute(ElasticRequest.search(firstSearchIndex, query)).documentAs[TestDocument]
} yield (assert(res)(Assertion.contains(document)) && assert(res)(!Assertion.contains(secondDocument)))
}
} @@ around(
Executor.execute(ElasticRequest.createIndex(firstSearchIndex)),
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie
),
test("search for first 2 documents using range query") {
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument, genDocumentId, genTestDocument) {
(firstDocumentId, firstDocument, secondDocumentId, secondDocument, thirdDocumentId, thirdDocument) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ import zio.schema.Schema

object ElasticQuery {

/**
* Constructs a type-safe instance of [[zio.elasticsearch.query.ConstantScoreQuery]] with a specified query.
* [[zio.elasticsearch.query.ConstantScoreQuery]] wraps a filter query and returns every matching document with a
* relevance score equal to the boost parameter value.
*
* @param query
* query to be wrapped inside of constant score query
* @tparam S
* document for which field query is specified for. An implicit `Schema` instance must be provided in the scope
* @return
* an instance of [[zio.elasticsearch.query.ConstantScoreQuery]] that represents the constant score query with query
* that must satisfy the criteria to be performed.
*/
final def constantScore[S: Schema](query: ElasticQuery[S]): ConstantScoreQuery[S] =
ConstantScore[S](query = query, boost = None)

/**
* Constructs an instance of [[zio.elasticsearch.query.ConstantScoreQuery]] with a specified query.
* [[zio.elasticsearch.query.ConstantScoreQuery]] wraps a filter query and returns every matching document with a
* relevance score equal to the boost parameter value.
*
* @param query
* query to be wrapped inside of constant score query
* @return
* an instance of [[zio.elasticsearch.query.ConstantScoreQuery]] that represents the constant score query with query
* that must satisfy the criteria to be performed.
*/
final def constantScore(query: ElasticQuery[Any]): ConstantScoreQuery[Any] =
ConstantScore[Any](query = query, 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 contains the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,22 @@ private[elasticsearch] final case class Bool[S](
}
}

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

private[elasticsearch] final case class ConstantScore[S](query: ElasticQuery[S], boost: Option[Double])
extends ConstantScoreQuery[S] { self =>

def boost(value: Double): ConstantScoreQuery[S] =
self.copy(boost = Some(value))

private[elasticsearch] def toJson(fieldPath: Option[String]): Json =
Obj(
"constant_score" -> (Obj("filter" -> query.toJson(fieldPath)) merge boost.fold(Obj())(b =>
Obj("boost" -> b.toJson)
))
)
}

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

private[elasticsearch] final case class Exists[S](field: String, boost: Option[Double]) extends ExistsQuery[S] { self =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,36 @@ object ElasticQuerySpec extends ZIOSpecDefault {
)
}
),
test("constantScore") {
val query = constantScore(terms("stringField", "a", "b", "c"))
val queryTs = constantScore(terms(TestDocument.stringField, "a", "b", "c"))
val queryWithBoost = constantScore(terms(TestDocument.stringField, "a", "b", "c")).boost(2.2)

assert(query)(
equalTo(
ConstantScore[Any](
Terms(field = "stringField", values = Chunk("a", "b", "c"), boost = None),
boost = None
)
)
) &&
assert(queryTs)(
equalTo(
ConstantScore[TestDocument](
Terms(field = "stringField", values = Chunk("a", "b", "c"), boost = None),
boost = None
)
)
) &&
assert(queryWithBoost)(
equalTo(
ConstantScore[TestDocument](
Terms(field = "stringField", values = Chunk("a", "b", "c"), boost = None),
boost = Some(2.2)
)
)
)
},
test("contains") {
val query = contains("testField", "test")
val queryTs = contains(TestDocument.stringField, "test")
Expand Down Expand Up @@ -1924,6 +1954,41 @@ object ElasticQuerySpec extends ZIOSpecDefault {
assert(queryWithAllParams.toJson(fieldPath = None))(equalTo(expectedWithAllParams.toJson))
}
),
test("constantScore") {
val query = constantScore(matchPhrase("stringField", "test"))
val queryTs = constantScore(matchPhrase(TestDocument.stringField, "test"))
val queryWithBoost = constantScore(matchPhrase(TestDocument.stringField, "test")).boost(1.5)

val expected =
"""
|{
| "constant_score": {
| "filter": {
| "match_phrase": {
| "stringField": "test"
| }
| }
| }
|}
|""".stripMargin
val expectedWithBoost =
"""
|{
| "constant_score": {
| "filter": {
| "match_phrase": {
| "stringField": "test"
| }
| },
| "boost": 1.5
| }
|}
|""".stripMargin

assert(query.toJson(fieldPath = None))(equalTo(expected.toJson)) &&
assert(queryTs.toJson(fieldPath = None))(equalTo(expected.toJson)) &&
assert(queryWithBoost.toJson(fieldPath = None))(equalTo(expectedWithBoost.toJson))
},
test("contains") {
val query = contains(TestDocument.stringField, "test")
val queryWithBoost = contains(TestDocument.stringField, "test").boost(3.14)
Expand Down
1 change: 1 addition & 0 deletions website/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = {
items: [
'overview/elastic_query',
'overview/queries/elastic_query_bool',
'overview/queries/elastic_query_constant_score',
'overview/queries/elastic_query_exists',
'overview/queries/elastic_query_function_score',
'overview/queries/elastic_query_geo_distance',
Expand Down

0 comments on commit 8b3d2fd

Please sign in to comment.