变体类型
编辑变体类型
编辑Elasticsearch API 有很多变体类型:查询、聚合、字段映射、分析器等等。在如此庞大的集合中找到正确的类名可能具有挑战性。
Java API 客户端构建器使这变得容易:变体类型的构建器(例如 Query
)为每个可用的实现提供了方法。我们已经在上面的示例中看到了 intervals
(一种查询)以及 allOf
、match
和 anyOf
(各种类型的间隔)。
这是因为 Java API 客户端中的变体对象是“标记联合”的实现:它们包含它们所持有的变体的标识符(或标记)以及该变体的值。例如,一个 Query
对象可以包含一个标记为 intervals
的 IntervalsQuery
、一个标记为 term
的 TermQuery
等等。这种方法允许编写流畅的代码,您可以在其中让 IDE 的代码补全功能引导您构建和导航复杂的嵌套结构。
变体构建器具有针对每个可用实现的设置方法。它们使用与常规属性相同的约定,并接受构建器 lambda 表达式和变体实际类型的现成对象。以下是一个构建 term 查询的示例:
Query query = new Query.Builder() .term(t -> t .field("name") .value(v -> v.stringValue("foo")) ) .build();
变体对象具有针对每个可用实现的 getter 方法。这些方法会检查对象是否实际包含该类型的变体,并将值向下转换为正确的类型。否则,它们会抛出一个 IllegalStateException
。这种方法允许编写流畅的代码来遍历变体。
assertEquals("foo", query.term().value().stringValue());
变体对象还提供有关它们当前持有的变体类型的信息
- 针对每种变体类型提供
is
方法:isTerm()
、isIntervals()
、isFuzzy()
等。 - 提供一个嵌套的
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()); }
Elasticsearch 插件提供的自定义扩展
编辑Elasticsearch 接受可以扩展多种类型可用变体的插件。这包括查询、聚合、文本分析器和分词器、摄取处理器等。
这些类型的 Java API 客户端类除了内置的变体外,还接受一个 _custom
变体。这允许您通过在请求中提供任意 JSON 来使用这些插件定义的扩展,并接收插件在响应中产生的任意 JSON。
在下面的示例中,我们使用一个假设的插件,该插件添加了一个 sphere-distance
聚合,该聚合根据文档与参考位置的距离对包含 3D 坐标的文档进行分组。
要创建自定义聚合,请使用 _custom()
聚合类型并提供插件定义的其标识符和参数。参数可以是任何可以序列化为 JSON 的对象或值。在下面的示例中,我们使用一个简单的映射:
Map<String, Object> params = new HashMap<>(); params.put("interval", 10); params.put("scale", "log"); params.put("origin", new Double[]{145.0, 12.5, 1649.0}); SearchRequest request = SearchRequest.of(r -> r .index("stars") .aggregations("neighbors", agg -> agg ._custom("sphere-distance", params) ) );
自定义变体的结果以 JsonData
对象表示的原始 JSON 返回。然后,您可以遍历 JSON 树以获取数据。由于这并不总是方便的,您还可以定义表示该 JSON 数据的类,并从原始 JSON 中反序列化它们。
遍历 JSON 树
SearchResponse<Void> response = esClient.search(request, Void.class); JsonData neighbors = response .aggregations().get("neighbors") ._custom(); JsonArray buckets = neighbors.toJson() .asJsonObject() .getJsonArray("buckets"); for (JsonValue item : buckets) { JsonObject bucket = item.asJsonObject(); double key = bucket.getJsonNumber("key").doubleValue(); double docCount = bucket.getJsonNumber("doc_count").longValue(); doSomething(key, docCount); }
如果您只对聚合结果感兴趣,而不是搜索命中(另请参阅 聚合),请使用 |
|
以自定义 JSON 结果获取 |
|
遍历 JSON 树以提取结果数据。 |
使用表示自定义聚合结果的类
SearchResponse<Void> response = esClient.search(request, Void.class); SphereDistanceAggregate neighbors = response .aggregations().get("neighbors") ._custom() .to(SphereDistanceAggregate.class); for (Bucket bucket : neighbors.buckets()) { doSomething(bucket.key(), bucket.docCount()); }
其中 SphereDistanceAggregate
可以定义如下:
public static class SphereDistanceAggregate { private final List<Bucket> buckets; @JsonCreator public SphereDistanceAggregate( @JsonProperty("buckets") List<Bucket> buckets ) { this.buckets = buckets; } public List<Bucket> buckets() { return buckets; }; } public static class Bucket { private final double key; private final double docCount; @JsonCreator public Bucket( @JsonProperty("key") double key, @JsonProperty("doc_count") double docCount) { this.key = key; this.docCount = docCount; } public double key() { return key; } public double docCount() { return docCount; } }
上面示例的源代码可以在 Java API 客户端测试中找到。