构建 API 对象编辑

构建器对象编辑

Java API 客户端中的所有数据类型都是不可变的。对象创建使用 构建器模式,该模式在 2008 年的 Effective Java 中流行起来。

ElasticsearchClient client = ...
CreateIndexResponse createResponse = client.indices().create(
    new CreateIndexRequest.Builder()
        .index("my-index")
        .aliases("foo",
            new Alias.Builder().isWriteIndex(true).build()
        )
        .build()
);

请注意,在调用构建器的 build() 方法后,不应重复使用该构建器。

构建器 lambda 表达式编辑

虽然这很好用,但必须实例化构建器类并调用 build() 方法有点冗长。因此,Java API 客户端中的每个属性设置器也接受一个 lambda 表达式,该表达式以新创建的构建器作为参数,并返回一个填充的构建器。上面的代码片段也可以写成

ElasticsearchClient client = ...
CreateIndexResponse createResponse = client.indices()
    .create(createIndexBuilder -> createIndexBuilder
        .index("my-index")
        .aliases("foo", aliasBuilder -> aliasBuilder
            .isWriteIndex(true)
        )
    );

这种方法允许使用更简洁的代码,并且还避免了导入类(甚至记住它们的名称),因为类型是从方法参数签名推断出来的。

请注意,在上面的示例中,构建器变量仅用于启动属性设置器的链。因此,这些变量的名称并不重要,可以缩短以提高可读性。

ElasticsearchClient client = ...
CreateIndexResponse createResponse = client.indices()
    .create(c -> c
        .index("my-index")
        .aliases("foo", a -> a
            .isWriteIndex(true)
        )
    );

构建器 lambda 在处理复杂的嵌套查询时特别有用,例如以下查询,摘自 intervals 查询 API 文档

此示例还突出显示了深度嵌套结构中构建器参数的有用命名约定。对于只有一个参数的 lambda 表达式,Kotlin 提供了隐式 it 参数,Scala 允许使用 _。这可以通过在 Java 中使用下划线或单个字母前缀加表示深度级别的数字来近似(例如,_0_1b0b1 等)。这不仅消除了创建一次性变量名的需要,而且还提高了代码的可读性。正确的缩进还可以使查询的结构突出显示。

ElasticsearchClient client = ...
SearchResponse<SomeApplicationData> results = client
    .search(b0 -> b0
        .query(b1 -> b1
            .intervals(b2 -> b2
                .field("my_text")
                .allOf(b3 -> b3
                    .ordered(true)
                    .intervals(b4 -> b4
                        .match(b5 -> b5
                            .query("my favorite food")
                            .maxGaps(0)
                            .ordered(true)
                        )
                    )
                    .intervals(b4 -> b4
                        .anyOf(b5 -> b5
                            .intervals(b6 -> b6
                                .match(b7 -> b7
                                    .query("hot water")
                                )
                            )
                            .intervals(b6 -> b6
                                .match(b7 -> b7
                                    .query("cold porridge")
                                )
                            )
                        )
                    )
                )
            )
        ),
    SomeApplicationData.class 
);

搜索结果将映射到 SomeApplicationData 实例,以便应用程序可以轻松使用。

上面示例的源代码可以在 Java API 客户端测试 中找到。