-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(dsl): Support matchBooleanPrefix
query
#304
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
id: elastic_query_match_boolean_prefix | ||
title: "Match Boolean Prefix Query" | ||
--- | ||
|
||
The `MatchBooleanPrefix` query analyzes its input and constructs a `bool` query from the terms. Each term except the last is used in a `term` query. | ||
The last term is used in a `prefix` query. | ||
|
||
In order to use the `MatchBooleanPrefix` query import the following: | ||
```scala | ||
import zio.elasticsearch.query.MatchBooleanPrefixQuery | ||
import zio.elasticsearch.ElasticQuery._ | ||
``` | ||
|
||
You can create a `MatchBooleanPrefix` query using the `matchBooleanPrefix` method this way: | ||
```scala | ||
val query: MatchBooleanPrefixQuery = matchBooleanPrefix(field = "stringField", value = "test") | ||
``` | ||
|
||
You can create a [type-safe](https://lambdaworks.github.io/zio-elasticsearch/overview/overview_zio_prelude_schema) `MatchBooleanPrefix` query using the `matchBooleanPrefix` method this way: | ||
```scala | ||
val query: MatchBooleanPrefixQuery = matchBooleanPrefix(field = Document.stringField, value = "test") | ||
``` | ||
|
||
You can find more information about `MatchBooleanPrefix` query [here](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-match-bool-prefix-query.html). | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unnecessary new line. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -917,6 +917,48 @@ object HttpExecutorSpec extends IntegrationSpec { | |
Executor.execute(ElasticRequest.createIndex(firstSearchIndex)), | ||
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie | ||
), | ||
test("search for a document using a match boolean prefix query") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Write just one it-test for this query. There is no need to check |
||
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument) { | ||
(firstDocumentId, firstDocument, secondDocumentId, secondDocument) => | ||
for { | ||
_ <- Executor.execute(ElasticRequest.deleteByQuery(firstSearchIndex, matchAll)) | ||
document = firstDocument.copy(stringField = "test this is boolean") | ||
_ <- | ||
Executor.execute(ElasticRequest.upsert[TestDocument](firstSearchIndex, firstDocumentId, document)) | ||
_ <- Executor.execute( | ||
ElasticRequest | ||
.upsert[TestDocument](firstSearchIndex, secondDocumentId, secondDocument) | ||
.refreshTrue | ||
) | ||
query = matchBooleanPrefix(TestDocument.stringField, "this is test bo") | ||
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 a document using a match boolean prefix query with minimumShouldMatch") { | ||
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument) { | ||
(firstDocumentId, firstDocument, secondDocumentId, secondDocument) => | ||
for { | ||
_ <- Executor.execute(ElasticRequest.deleteByQuery(firstSearchIndex, matchAll)) | ||
document = firstDocument.copy(stringField = "test this is boolean") | ||
_ <- | ||
Executor.execute(ElasticRequest.upsert[TestDocument](firstSearchIndex, firstDocumentId, document)) | ||
_ <- Executor.execute( | ||
ElasticRequest | ||
.upsert[TestDocument](firstSearchIndex, secondDocumentId, secondDocument) | ||
.refreshTrue | ||
) | ||
query = matchBooleanPrefix(TestDocument.stringField, "this test bo").minimumShouldMatch(4) | ||
res <- Executor.execute(ElasticRequest.search(firstSearchIndex, query)).documentAs[TestDocument] | ||
} yield assert(res)(!Assertion.contains(document)) | ||
} | ||
} @@ around( | ||
Executor.execute(ElasticRequest.createIndex(firstSearchIndex)), | ||
Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie | ||
), | ||
test("search for a document using a match phrase query") { | ||
checkOnce(genDocumentId, genTestDocument, genDocumentId, genTestDocument) { | ||
(firstDocumentId, firstDocument, secondDocumentId, secondDocument) => | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -415,6 +415,44 @@ object ElasticQuery { | |||||
final def matches[A: ElasticPrimitive](field: String, value: A): MatchQuery[Any] = | ||||||
Match(field = field, value = value) | ||||||
|
||||||
/** | ||||||
* Constructs a type-safe instance of [[zio.elasticsearch.query.MatchBooleanPrefixQuery]] using the specified | ||||||
* parameters. [[zio.elasticsearch.query.MatchBooleanPrefixQuery]] analyzes its input and constructs a `bool` query | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make bool query a reference. |
||||||
* from the terms. Each term except the last is used in a `term` query. The last term is used in a `prefix` query. | ||||||
* | ||||||
* @param field | ||||||
* the type-safe field for which query is specified for | ||||||
* @param value | ||||||
* the value to be matched, represented by an instance of type `A` | ||||||
* @tparam S | ||||||
* document for which field query is executed | ||||||
* @tparam A | ||||||
* the type of value to be matched. A JSON decoder must be in scope for this type | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
* @return | ||||||
* an instance of [[zio.elasticsearch.query.MatchBooleanPrefixQuery]] that represents the match boolean prefix query | ||||||
* to be performed. | ||||||
*/ | ||||||
final def matchBooleanPrefix[S, A: ElasticPrimitive](field: Field[S, A], value: A): MatchBooleanPrefixQuery[S] = | ||||||
MatchBooleanPrefix(field = field.toString, value, minimumShouldMatch = None) | ||||||
|
||||||
/** | ||||||
* Constructs an instance of [[zio.elasticsearch.query.MatchBooleanPrefixQuery]] using the specified parameters. | ||||||
* [[zio.elasticsearch.query.MatchBooleanPrefixQuery]] analyzes its input and constructs a `bool` query from the | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||||||
* terms. Each term except the last is used in a `term` query. The last term is used in a `prefix` query. | ||||||
* | ||||||
* @param field | ||||||
* the field for which query is specified for | ||||||
* @param value | ||||||
* the value to be matched, represented by an instance of type `A` | ||||||
* @tparam A | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||||||
* the type of value to be matched. A JSON decoder must be in scope for this type | ||||||
* @return | ||||||
* an instance of [[zio.elasticsearch.query.MatchBooleanPrefixQuery]] that represents the match boolean prefix query | ||||||
* to be performed. | ||||||
*/ | ||||||
final def matchBooleanPrefix[A: ElasticPrimitive](field: String, value: A): MatchBooleanPrefixQuery[Any] = | ||||||
MatchBooleanPrefix(field = field, value = value, minimumShouldMatch = None) | ||||||
|
||||||
/** | ||||||
* Constructs a type-safe instance of [[zio.elasticsearch.query.MatchPhraseQuery]] using the specified parameters. | ||||||
* [[zio.elasticsearch.query.MatchPhraseQuery]] analyzes the text and creates a phrase query out of the analyzed text. | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -567,6 +567,26 @@ private[elasticsearch] final case class MatchAll(boost: Option[Double]) extends | |
Obj("match_all" -> Obj(Chunk.fromIterable(boost.map("boost" -> _.toJson)))) | ||
} | ||
|
||
sealed trait MatchBooleanPrefixQuery[S] extends ElasticQuery[S] with HasMinimumShouldMatch[MatchBooleanPrefixQuery[S]] | ||
|
||
private[elasticsearch] final case class MatchBooleanPrefix[S, A: ElasticPrimitive]( | ||
field: String, | ||
value: A, | ||
minimumShouldMatch: Option[Int] | ||
) extends MatchBooleanPrefixQuery[S] { self => | ||
def minimumShouldMatch(value: Int): MatchBooleanPrefixQuery[S] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put an empty line between. |
||
self.copy(minimumShouldMatch = Some(value)) | ||
|
||
private[elasticsearch] def toJson(fieldPath: Option[String]): Json = | ||
Obj( | ||
"match_bool_prefix" -> Obj( | ||
fieldPath.foldRight(field)(_ + "." + _) -> minimumShouldMatch.fold(value.toJson)(m => | ||
Obj("query" -> value.toJson) merge Obj("minimum_should_match" -> m.toJson) | ||
) | ||
) | ||
) | ||
} | ||
|
||
sealed trait MatchPhraseQuery[S] extends ElasticQuery[S] with HasBoost[MatchPhraseQuery[S]] | ||
|
||
private[elasticsearch] final case class MatchPhrase[S](field: String, value: String, boost: Option[Double]) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -873,6 +873,53 @@ object ElasticQuerySpec extends ZIOSpecDefault { | |
equalTo(Match[TestDocument, Double](field = "doubleField", value = 3.14)) | ||
) | ||
}, | ||
test("matchBooleanPrefix") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add one test for query with suffix (for creating json too). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move this between |
||
val queryString = matchBooleanPrefix("stringField", "test") | ||
val queryBool = matchBooleanPrefix("booleanField", true) | ||
val queryInt = matchBooleanPrefix("intField", 1) | ||
val queryWithMinimumShouldMatch = matchBooleanPrefix("stringField", "test").minimumShouldMatch(3) | ||
val queryStringTs = matchBooleanPrefix(TestDocument.stringField, "test") | ||
val queryBoolTs = matchBooleanPrefix(TestDocument.booleanField, true) | ||
val queryIntTs = matchBooleanPrefix(TestDocument.intField, 1) | ||
val queryWithMinimumShouldMatchTs = matchBooleanPrefix(TestDocument.stringField, "test").minimumShouldMatch(3) | ||
|
||
assert(queryString)( | ||
equalTo(MatchBooleanPrefix[Any, String](field = "stringField", value = "test", minimumShouldMatch = None)) | ||
) && | ||
assert(queryBool)( | ||
equalTo(MatchBooleanPrefix[Any, Boolean](field = "booleanField", value = true, minimumShouldMatch = None)) | ||
) && | ||
assert(queryInt)( | ||
equalTo(MatchBooleanPrefix[Any, Int](field = "intField", value = 1, minimumShouldMatch = None)) | ||
) && | ||
assert(queryWithMinimumShouldMatch)( | ||
equalTo( | ||
MatchBooleanPrefix[Any, String](field = "stringField", value = "test", minimumShouldMatch = Some(3)) | ||
) | ||
) && | ||
assert(queryStringTs)( | ||
equalTo( | ||
MatchBooleanPrefix[TestDocument, String](field = "stringField", value = "test", minimumShouldMatch = None) | ||
) | ||
) && | ||
assert(queryBoolTs)( | ||
equalTo( | ||
MatchBooleanPrefix[TestDocument, Boolean](field = "booleanField", value = true, minimumShouldMatch = None) | ||
) | ||
) && | ||
assert(queryIntTs)( | ||
equalTo(MatchBooleanPrefix[TestDocument, Int](field = "intField", value = 1, minimumShouldMatch = None)) | ||
) && | ||
assert(queryWithMinimumShouldMatchTs)( | ||
equalTo( | ||
MatchBooleanPrefix[TestDocument, String]( | ||
field = "stringField", | ||
value = "test", | ||
minimumShouldMatch = Some(3) | ||
) | ||
) | ||
) | ||
}, | ||
test("matchPhrase") { | ||
val query = matchPhrase("stringField", "this is a test") | ||
val queryTs = matchPhrase(TestDocument.stringField, "this is a test") | ||
|
@@ -2427,6 +2474,66 @@ object ElasticQuerySpec extends ZIOSpecDefault { | |
assert(queryTsInt.toJson(fieldPath = None))(equalTo(expectedTsInt.toJson)) && | ||
assert(queryTsString.toJson(fieldPath = None))(equalTo(expectedTsString.toJson)) | ||
}, | ||
test("matchBooleanPrefix") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move this between |
||
val queryString = matchBooleanPrefix("stringField", "test") | ||
val queryBool = matchBooleanPrefix("booleanField", true) | ||
val queryInt = matchBooleanPrefix("intField", 1) | ||
val queryWithMinimumShouldMatch = matchBooleanPrefix("stringField", "test").minimumShouldMatch(3) | ||
val queryStringTs = matchBooleanPrefix(TestDocument.stringField, "test") | ||
val queryBoolTs = matchBooleanPrefix(TestDocument.booleanField, true) | ||
val queryIntTs = matchBooleanPrefix(TestDocument.intField, 1) | ||
val queryWithMinimumShouldMatchTs = matchBooleanPrefix(TestDocument.stringField, "test").minimumShouldMatch(3) | ||
|
||
val expectedString = | ||
""" | ||
|{ | ||
| "match_bool_prefix": { | ||
| "stringField": "test" | ||
| } | ||
|} | ||
|""".stripMargin | ||
|
||
val expectedBool = | ||
""" | ||
|{ | ||
| "match_bool_prefix": { | ||
| "booleanField": true | ||
| } | ||
|} | ||
|""".stripMargin | ||
|
||
val expectedInt = | ||
""" | ||
|{ | ||
| "match_bool_prefix": { | ||
| "intField": 1 | ||
| } | ||
|} | ||
|""".stripMargin | ||
|
||
val expectedWithMinimumShouldMatch = | ||
""" | ||
|{ | ||
| "match_bool_prefix": { | ||
| "stringField": { | ||
| "query": "test", | ||
| "minimum_should_match": 3 | ||
| } | ||
| } | ||
|} | ||
|""".stripMargin | ||
|
||
assert(queryString.toJson(fieldPath = None))(equalTo(expectedString.toJson)) && | ||
assert(queryBool.toJson(fieldPath = None))(equalTo(expectedBool.toJson)) && | ||
assert(queryInt.toJson(fieldPath = None))(equalTo(expectedInt.toJson)) && | ||
assert(queryWithMinimumShouldMatch.toJson(fieldPath = None))( | ||
equalTo(expectedWithMinimumShouldMatch.toJson) | ||
) && | ||
assert(queryStringTs.toJson(fieldPath = None))(equalTo(expectedString.toJson)) && | ||
assert(queryBoolTs.toJson(fieldPath = None))(equalTo(expectedBool.toJson)) && | ||
assert(queryIntTs.toJson(fieldPath = None))(equalTo(expectedInt.toJson)) && | ||
assert(queryWithMinimumShouldMatchTs.toJson(fieldPath = None))(equalTo(expectedWithMinimumShouldMatch.toJson)) | ||
}, | ||
test("matchPhrase") { | ||
val querySimple = matchPhrase("stringField", "this is a test") | ||
val queryRaw = matchPhrase("stringField.raw", "this is a test") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please show using of
miniumum_should_match
parameter in doc.