Skip to main content

Overview

In order to execute Elasticsearch query requests, both for searching and deleting by query, you first must specify the type of the query along with the corresponding parameters for that type. Queries are described with the ElasticQuery data type, which can be constructed from the DSL methods found under the following import:

import zio.elasticsearch.ElasticQuery._

Query DSL methods that require a field solely accept field types that are defined as Elasticsearch primitives. You can pass field names simply as strings, or you can use the type-safe query methods that make use of ZIO Schema's accessors. An example with a term query is shown below:

import zio.elasticsearch.ElasticQuery._

final case class User(id: Int, name: String)

object User {
implicit val schema: Schema.CaseClass2[Int, String, User] =
DeriveSchema.gen[User]

val (id, name) = schema.makeAccessors(FieldAccessorBuilder)
}

term("name", "John Doe")

// type-safe method
term(field = User.name, value = "John Doe")

You can also represent a field from nested structures with type-safe query methods, using the / operator on accessors:

import zio._
import zio.elasticsearch._
import zio.elasticsearch.ElasticQuery._
import zio.schema.annotation.fieldName
import zio.schema.{DeriveSchema, Schema}

final case class Name(
@fieldName("first_name")
firstName: String,
@fieldName("last_name")
lastName: String
)

object Name {
implicit val schema: Schema.CaseClass2[String, String, Name] = DeriveSchema.gen[Name]

val (firstName, lastName) = schema.makeAccessors(FieldAccessorBuilder)
}

final case class User(id: String, name: Name, email: String, age: Int)

object User {
implicit val schema: Schema.CaseClass4[String, Name, String, Int, User] =
DeriveSchema.gen[User]

val (id, name, email, age) = schema.makeAccessors(FieldAccessorBuilder)
}

matches(field = "name.first_name", value = "John")

// type-safe method
matches(field = User.name / Name.firstName, value = "John")

Accessors also have a suffix method, in case you want to use one in queries:

ElasticQuery.term("email.keyword", "jane.doe@lambdaworks.io")

// type-safe method
ElasticQuery.term(User.email.suffix("keyword"), "jane.doe@lambdaworks.io")

In case the suffix is "keyword" or "raw" you can use keyword and raw methods respectively.

Now, after describing a query, you can pass it to the search/deleteByQuery method to obtain the ElasticRequest corresponding to that query:

ElasticRequest.search(IndexName("index"), term(field = "name.first_name.keyword", value = "John"))

// type-safe method
ElasticRequest.search(IndexName("index"), term(field = User.name / Name.firstName.keyword, value = "John"))