Skip to content

Commit

Permalink
Support terms enum api (#3075)
Browse files Browse the repository at this point in the history
  • Loading branch information
Philippus committed May 31, 2024
1 parent f9ad561 commit f569ab7
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sksamuel.elastic4s

import com.sksamuel.elastic4s.api.{AggregationApi, AliasesApi, AnalyzeApi, AnalyzerApi, BulkApi, CatsApi, ClearRolesCacheApi, ClusterApi, CollapseApi, CountApi, CreateIndexApi, CreateRoleApi, CreateUserApi, DeleteApi, DeleteIndexApi, DeleteRoleApi, DeleteUserApi, ExistsApi, ExplainApi, ForceMergeApi, GetApi, HighlightApi, IndexAdminApi, IndexApi, IndexRecoveryApi, IndexTemplateApi, IngestApi, KnnApi, LocksApi, MappingApi, NodesApi, NormalizerApi, PipelineAggregationApi, PitApi, QueryApi, ReindexApi, ReloadSearchAnalyzersApi, RoleApi, ScoreApi, ScriptApi, ScrollApi, SearchApi, SearchTemplateApi, SettingsApi, SnapshotApi, SortApi, StoredScriptApi, SuggestionApi, SynonymsApi, TaskApi, TermVectorApi, TokenFilterApi, TokenizerApi, TypesApi, UpdateApi, UserAdminApi, UserApi, ValidateApi}
import com.sksamuel.elastic4s.api.{AggregationApi, AliasesApi, AnalyzeApi, AnalyzerApi, BulkApi, CatsApi, ClearRolesCacheApi, ClusterApi, CollapseApi, CountApi, CreateIndexApi, CreateRoleApi, CreateUserApi, DeleteApi, DeleteIndexApi, DeleteRoleApi, DeleteUserApi, ExistsApi, ExplainApi, ForceMergeApi, GetApi, HighlightApi, IndexAdminApi, IndexApi, IndexRecoveryApi, IndexTemplateApi, IngestApi, KnnApi, LocksApi, MappingApi, NodesApi, NormalizerApi, PipelineAggregationApi, PitApi, QueryApi, ReindexApi, ReloadSearchAnalyzersApi, RoleApi, ScoreApi, ScriptApi, ScrollApi, SearchApi, SearchTemplateApi, SettingsApi, SnapshotApi, SortApi, StoredScriptApi, SuggestionApi, SynonymsApi, TaskApi, TermVectorApi, TermsEnumApi, TokenFilterApi, TokenizerApi, TypesApi, UpdateApi, UserAdminApi, UserApi, ValidateApi}

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

Expand Down Expand Up @@ -55,6 +56,7 @@ trait ElasticApi
with SynonymsApi
with TaskApi
with TermVectorApi
with TermsEnumApi
with TokenizerApi
with TokenFilterApi
with TypesApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.sksamuel.elastic4s.handlers.settings.SettingsHandlers
import com.sksamuel.elastic4s.handlers.snapshot.SnapshotHandlers
import com.sksamuel.elastic4s.handlers.synonyms.SynonymsHandlers
import com.sksamuel.elastic4s.handlers.task.TaskHandlers
import com.sksamuel.elastic4s.handlers.termsenum.TermsEnumHandlers
import com.sksamuel.elastic4s.handlers.termvectors.TermVectorHandlers
import com.sksamuel.elastic4s.handlers.update.UpdateHandlers
import com.sksamuel.elastic4s.handlers.validate.ValidateHandlers
Expand Down Expand Up @@ -66,6 +67,7 @@ with SynonymsHandlers
with UpdateHandlers
with TaskHandlers
with TermVectorHandlers
with TermsEnumHandlers
with UserAdminHandlers
with UserHandlers
with ValidateHandlers
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.sksamuel.elastic4s.api

import com.sksamuel.elastic4s.Indexes
import com.sksamuel.elastic4s.requests.termsenum.TermsEnumRequest
trait TermsEnumApi {
def termsEnum(index: String, field: String): TermsEnumRequest = TermsEnumRequest(Indexes(index), field)
def termsEnum(indexes: Indexes, field: String): TermsEnumRequest = TermsEnumRequest(indexes, field)
def termsEnum(indexes: Seq[String], field: String): TermsEnumRequest = TermsEnumRequest(Indexes(indexes), field)

def termsEnum(index: String, field: String, string: String): TermsEnumRequest = TermsEnumRequest(Indexes(index), field, string = Some(string))
def termsEnum(indexes: Indexes, field: String, string: String): TermsEnumRequest = TermsEnumRequest(indexes, field, string = Some(string))
def termsEnum(indexes: Seq[String], field: String, string: String): TermsEnumRequest = TermsEnumRequest(Indexes(indexes), field, string = Some(string))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sksamuel.elastic4s.requests.termsenum

import com.sksamuel.elastic4s.Indexes
import com.sksamuel.elastic4s.requests.searches.queries.Query
import com.sksamuel.elastic4s.ext.OptionImplicits._

case class TermsEnumRequest(indexes: Indexes,
field: String,
string: Option[String] = None,
size: Option[Int] = None,
timeout: Option[String] = None,
caseInsensitive: Option[Boolean] = None,
indexFilter: Option[Query] = None,
searchAfter: Option[String] = None
) extends Serializable {
def string(string: String): TermsEnumRequest = copy(string = string.some)
def size(size: Int): TermsEnumRequest = copy(size = size.some)
def timeout(timeout: String): TermsEnumRequest = copy(timeout = timeout.some)
def caseInsensitive(caseInsensitive: Boolean): TermsEnumRequest = copy(caseInsensitive = caseInsensitive.some)
def indexFilter(indexFilter: Query): TermsEnumRequest = copy(indexFilter = indexFilter.some)
def searchAfter(searchAfter: String): TermsEnumRequest = copy(searchAfter = searchAfter.some)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.sksamuel.elastic4s.requests.termsenum

import com.fasterxml.jackson.annotation.JsonProperty
import com.sksamuel.elastic4s.requests.common.Shards

case class TermsEnumResponse(terms: Seq[String], complete: Boolean, @JsonProperty("_shards") shards: Shards) {
def isComplete: Boolean = complete
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.sksamuel.elastic4s.handlers.termsenum

import com.sksamuel.elastic4s.handlers.searches.queries
import com.sksamuel.elastic4s.json.{XContentBuilder, XContentFactory}
import com.sksamuel.elastic4s.requests.termsenum.{TermsEnumRequest, TermsEnumResponse}
import com.sksamuel.elastic4s.{ElasticRequest, Handler, HttpEntity}

object TermsEnumBodyFn {
def apply(request: TermsEnumRequest): XContentBuilder = {
val builder = XContentFactory.jsonBuilder()
builder.field("field", request.field)
request.string.foreach(builder.field("string", _))
request.size.foreach(builder.field("size", _))
request.timeout.foreach(builder.field("timeout", _))
request.caseInsensitive.foreach(builder.field("case_insensitive", _))
request.indexFilter.foreach(q => builder.rawField("index_filter", queries.QueryBuilderFn(q)))
request.searchAfter.foreach(builder.field("search_after", _))
builder.endObject()
}
}

trait TermsEnumHandlers {
implicit object TermsEnumHandler extends Handler[TermsEnumRequest, TermsEnumResponse] {
override def build(request: TermsEnumRequest): ElasticRequest = {

val endpoint = s"/${request.indexes.values.mkString(",")}/_terms_enum"

val body = TermsEnumBodyFn(request).string
val entity = HttpEntity(body, "application/json")

ElasticRequest("POST", endpoint, entity)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.sksamuel.elastic4s.requests.termsenum

import scala.util.Try

import com.sksamuel.elastic4s.handlers.termsenum.TermsEnumBodyFn
import com.sksamuel.elastic4s.requests.common.RefreshPolicy
import com.sksamuel.elastic4s.requests.searches.term.TermQuery
import com.sksamuel.elastic4s.testkit.DockerTests
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class TermsEnumTest extends AnyWordSpec with Matchers with DockerTests {
Try {
client.execute {
deleteIndex("test")
}.await
}

client.execute {
createIndex("test").mapping(
properties(
keywordField("tags"),
)
)
}.await

client.execute {
indexInto("test") fields(
"tags" -> "kibana"
) refresh RefreshPolicy.WaitFor
}.await

"a minimal terms enum query" should {
"return proper response" in {
val resp = client.execute {
termsEnum("test", "tags", "kiba")
}.await.result
resp.terms shouldBe Seq("kibana")
resp.isComplete shouldBe true
}

val termsEnumRequest = TermsEnumRequest("test", "tags")
.string("kiba")
.size(3)
.timeout("1m")
.caseInsensitive(false)
.indexFilter(TermQuery("tags", "kiba"))
.searchAfter("kiba")

"support all fields in the builder" in {
TermsEnumBodyFn(termsEnumRequest).string shouldEqual
"""{"field":"tags","string":"kiba","size":3,"timeout":"1m","case_insensitive":false,"index_filter":{"term":{"tags":{"value":"kiba"}}},"search_after":"kiba"}"""
}

"return a response when all fields are present" in {
val resp = client.execute {
termsEnumRequest
}.await.result
resp.terms shouldBe Seq("kibana")
resp.isComplete shouldBe true
}
}
}

0 comments on commit f569ab7

Please sign in to comment.