-
Notifications
You must be signed in to change notification settings - Fork 20
(dsl): Support intervalQuery #647
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
base: main
Are you sure you want to change the base?
Changes from 24 commits
861a986
7bb2df6
907980b
3b97832
ee269c2
441fe9f
af9b2fe
805f6bd
f9a4a13
84c908b
d5b8bc8
7af2c13
ba54dc1
593f575
5f42ed1
ff1916d
ca243e9
640500d
6308187
41df198
f7cb287
a136f4f
7391cec
45bc91e
cf31617
3f44d44
dfece62
500610f
72715df
7941fe3
26150f1
4d60d5f
c7eab4e
377bf8c
b21a202
b14e4d9
72e782b
626dfda
61a4949
1aae089
689ab2e
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,67 @@ | ||
| --- | ||
| id: elastic_interval_query | ||
| title: "Overview" | ||
| --- | ||
| The `Intervals` query allows for advanced search queries based on intervals between words in specific fields. | ||
| This query provides flexibility for conditions. | ||
|
|
||
| To use the `Intervals` query, import the following: | ||
| ```scala | ||
| import zio.elasticsearch.query.IntervalQuery | ||
| import zio.elasticsearch.ElasticQuery._ | ||
| ``` | ||
|
|
||
| You can create a basic `Intervals` query` using the `intervals` method: | ||
| ```scala | ||
| val query: IntervalQuery[Any] = intervals(field = "content", rule = intervalMatch("targetWord")) | ||
| ``` | ||
|
|
||
| If you want to specify which fields should be searched, you can use the `useField` method: | ||
| ```scala | ||
| val queryWithField: IntervalQuery[Document] = | ||
| intervals(field = "content", rule = intervalMatch("targetWord").useField(Document.stringField)) | ||
| ``` | ||
|
|
||
| To define `field` in a type-safe manner, use the overloaded `useField` method with field definitions from your document: | ||
| ```scala | ||
| val queryWithSafeField: IntervalQuery[Document] = | ||
| intervals(field = Document.stringField, rule = intervalMatch("targetWord")) | ||
| ``` | ||
markok4 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Alternatively, you can pass a `Field` object directly: | ||
| ```scala | ||
| val queryWithFieldObject: IntervalQuery[Document] = | ||
| intervals(field = "content", rule = intervalMatch("targetWord").useField(Document.stringField)) | ||
| ``` | ||
|
||
|
|
||
| If you want to define the `maxGaps` parameter, use the `maxGaps` method: | ||
| ```scala | ||
| val queryWithMaxGaps: IntervalQuery[Document] = | ||
| intervals(field = "content", rule = intervalMatch("targetWord").maxGaps(2)) | ||
| ``` | ||
|
|
||
| If you want to specify the word order requirement, use the `orderedOn` method: | ||
| ```scala | ||
| val queryWithOrder: IntervalQuery[Document] = | ||
| intervals(field = "content", rule = intervalMatch("targetWord").orderedOn()) | ||
| ``` | ||
|
|
||
| You can also apply additional filters to the query: | ||
| ```scala | ||
| val queryWithFilter: IntervalQuery[Document] = | ||
| intervals(field = "content", rule = intervalMatch("targetWord").filter(IntervalFilter.someFilter)) | ||
| ``` | ||
|
|
||
| Alternatively, you can construct the query manually with all parameters: | ||
| ```scala | ||
| val queryManually: IntervalQuery[Document] = | ||
| IntervalQuery( | ||
| field = "content", | ||
| rule = intervalMatch("targetWord") | ||
| .maxGaps(2) | ||
| .orderedOn() | ||
| .filter(IntervalFilter.someFilter) | ||
| .analyzer("standard") | ||
| ) | ||
| ``` | ||
|
|
||
markok4 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,31 +1,16 @@ | ||
| /* | ||
| * Copyright 2022 LambdaWorks | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
|
Collaborator
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. Why is this removed!?
Collaborator
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. You have resolved this comment, but you are still missing copyright here. |
||
| package zio.elasticsearch | ||
|
|
||
| import zio.Chunk | ||
| import zio.elasticsearch.ElasticAggregation._ | ||
| import zio.elasticsearch.ElasticHighlight.highlight | ||
| import zio.elasticsearch.ElasticQuery.{script => _, _} | ||
| import zio.elasticsearch.ElasticQuery.{contains => _, _} | ||
| import zio.elasticsearch.ElasticSort.sortBy | ||
| import zio.elasticsearch.aggregation.AggregationOrder | ||
| import zio.elasticsearch.data.GeoPoint | ||
| import zio.elasticsearch.domain.{PartialTestDocument, TestDocument, TestSubDocument} | ||
| import zio.elasticsearch.executor.Executor | ||
| import zio.elasticsearch.query.DistanceUnit.Kilometers | ||
| import zio.elasticsearch.query.ElasticIntervalQuery.intervalMatch | ||
| import zio.elasticsearch.query.FunctionScoreFunction.randomScoreFunction | ||
| import zio.elasticsearch.query.MultiMatchType._ | ||
| import zio.elasticsearch.query.sort.SortMode.Max | ||
|
|
@@ -189,7 +174,8 @@ object HttpExecutorSpec extends IntegrationSpec { | |
| ) | ||
| .refreshTrue | ||
| ) | ||
| query = term(field = TestDocument.stringField, value = secondDocumentUpdated.stringField.toLowerCase) | ||
| query = | ||
| term(field = TestDocument.stringField, value = secondDocumentUpdated.stringField.toLowerCase) | ||
|
||
| aggregation = | ||
| filterAggregation(name = "aggregation", query = query).withSubAgg( | ||
| maxAggregation("subAggregation", TestDocument.intField) | ||
|
|
@@ -2771,6 +2757,69 @@ object HttpExecutorSpec extends IntegrationSpec { | |
| } | ||
| } @@ after(Executor.execute(ElasticRequest.deleteIndex(geoPolygonIndex)).orDie) | ||
| ), | ||
| suite("interval-match query")( | ||
markok4 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| test("intervalMatch returns only matching document") { | ||
| checkOnce(genDocumentId, genTestDocument, Gen.alphaNumericString, genDocumentId, genTestDocument) { | ||
| (idMatch, docMatch, targetWord, idNoMatch, docNoMatch) => | ||
| val docShouldMatch = docMatch.copy(stringField = s"prefix $targetWord suffix") | ||
| val docShouldNotMatch = docNoMatch.copy(stringField = "completely unrelated text") | ||
| val field = TestDocument.stringField.toString | ||
| val query = intervals(field, intervalMatch(targetWord)) | ||
markok4 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| for { | ||
| _ <- Executor.execute(ElasticRequest.deleteByQuery(firstSearchIndex, matchAll)) | ||
| _ <- Executor.execute(ElasticRequest.upsert(firstSearchIndex, idMatch, docShouldMatch)) | ||
| _ <- Executor.execute( | ||
| ElasticRequest.upsert(firstSearchIndex, idNoMatch, docShouldNotMatch).refreshTrue | ||
| ) | ||
| res <- Executor.execute(ElasticRequest.search(firstSearchIndex, query)).documentAs[TestDocument] | ||
| } yield assert(res)( | ||
| Assertion.contains(docShouldMatch) && | ||
| Assertion.not(Assertion.contains(docShouldNotMatch)) | ||
markok4 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ) | ||
| } | ||
| } @@ around( | ||
| Executor.execute(ElasticRequest.createIndex(firstSearchIndex)), | ||
| Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie | ||
| ), | ||
| test("intervalMatch query finds document with exact matching term") { | ||
| checkOnce(genDocumentId, genTestDocument) { (docId, doc) => | ||
| val term = "apple" | ||
| val docWithTerm = doc.copy(stringField = s"$term banana orange") | ||
|
|
||
| val query = intervals( | ||
| "stringField", | ||
|
||
| intervalMatch(term) | ||
| ) | ||
|
|
||
| for { | ||
| _ <- Executor.execute(ElasticRequest.upsert(firstSearchIndex, docId, docWithTerm)) | ||
| _ <- Executor.execute(ElasticRequest.refresh(firstSearchIndex)) | ||
| res <- Executor.execute(ElasticRequest.search(firstSearchIndex, query)).documentAs[TestDocument] | ||
| } yield assert(res)(Assertion.contains(docWithTerm)) | ||
| } | ||
| } @@ around( | ||
| Executor.execute(ElasticRequest.createIndex(firstSearchIndex)), | ||
| Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie | ||
| ), | ||
| test("intervalMatch query does not find document if term is absent") { | ||
| checkOnce(genDocumentId, genTestDocument) { (docId, doc) => | ||
| val query = intervals( | ||
| "stringField", | ||
| intervalMatch("nonexistentterm") | ||
| ) | ||
|
|
||
| for { | ||
| _ <- Executor.execute(ElasticRequest.upsert(firstSearchIndex, docId, doc)) | ||
| _ <- Executor.execute(ElasticRequest.refresh(firstSearchIndex)) | ||
| res <- Executor.execute(ElasticRequest.search(firstSearchIndex, query)).documentAs[TestDocument] | ||
| } yield assert(res)(Assertion.isEmpty) | ||
| } | ||
| } @@ around( | ||
| Executor.execute(ElasticRequest.createIndex(firstSearchIndex)), | ||
| Executor.execute(ElasticRequest.deleteIndex(firstSearchIndex)).orDie | ||
| ) | ||
| ), | ||
| suite("search for documents using FunctionScore query")( | ||
| test("using randomScore function") { | ||
| checkOnce(genTestDocument, genTestDocument) { (firstDocument, secondDocument) => | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.