Variant types
editVariant types
editThe Elasticsearch API has a lot of variant types: queries, aggregations, field mappings, analyzers, and so on. Finding the correct class name in such large collections can be challenging.
The Java API Client builders make this easy: the builders for variant types, such as
Query
, have methods for each of the available implementations. We’ve seen this
in action above with intervals
(a kind of query) and allOf
, match
and
anyOf
(various kinds of intervals).
This is because variant objects in the Java API Client are implementations of a
“tagged union”: they contain the identifier (or tag) of the variant they hold
and the value for that variant. For example, a Query
object can contain an
IntervalsQuery
with tag intervals
, a TermQuery
with tag term
, and so on.
This approach allows writing fluent code where you can let the IDE completion
features guide you to build and navigate complex nested structures:
Variant builders have setter methods for every available implementation. They use the same conventions as regular properties and accept both a builder lambda expression and a ready-made object of the actual type of the variant. Here’s an example to build a term query:
Query query = new Query.Builder() .term(t -> t .field("name") .value(v -> v.stringValue("foo")) ) .build();
Choose the |
|
Build the terms query with a builder lambda expression. |
|
Build the |
Variant objects have getter methods for every available implementation. These
methods check that the object actually holds a variant of that kind and return
the value downcasted to the correct type. They throw an IllegalStateException
otherwise. This approach allows writing fluent code to traverse variants.
assertEquals("foo", query.term().value().stringValue());
Variant objects also provide information on the variant kind they currently hold:
-
with
is
methods for each of the variant kinds:isTerm()
,isIntervals()
,isFuzzy()
, etc. -
with a nested
Kind
enumeration that defines all variant kinds.
This information can then be used to navigate down into specific variants after checking their actual kind:
if (query.isTerm()) { doSomething(query.term()); } switch(query._kind()) { case Term: doSomething(query.term()); break; case Intervals: doSomething(query.intervals()); break; default: doSomething(query._kind(), query._get()); }
Test if the variant is of a specific kind. |
|
Test a larger set of variant kinds. |
|
Get the kind and value held by the variant object. |
The source code for the examples above can be found in the Java API Client tests.