Elasticsearch tutorial(三)Java API

本文是关于Elasticsearch的Java API教程,涵盖了Maven配置、Indexing、Retrieving和Deleting以及Querying Indexed Documents。在Java API部分,讨论了如何使用Transport Client创建、检索和删除文档,并进行了简单的查询操作演示。
摘要由CSDN通过智能技术生成

概述

  Elasticesearch本身是Java语言开发的,天生对Java支持的最好。因此我们用Java来开发相关接口是一个不错的选择。(当前用于测试的elasticsearch版本均为<es.version>5.6.14</es.version>)

Maven配置

在我们的mvn项目中的pom.xml中增加以下代码

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>${es.version}</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>${es.version}</version>
</dependency>

Java API

  在我们正式开始之前,我们需要初始化我们的transport client的相关settings:

@Data
@Configuration
@PropertySource("classpath:elasticsearch.properties")
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig {

    private String clusterName;
    private String host;
    private int port;
}

@Getter
@Component
public final class ClientSetting implements InitializingBean {

    private InetSocketTransportAddress address;
    private Settings settings;

    @Autowired
    private ElasticSearchConfig config;

    @Override
    public void afterPropertiesSet() throws Exception {
        address = new InetSocketTransportAddress(InetAddress.getByName(config.getHost()), config.getPort());
        settings = Settings.builder()
            .put("client.transport.sniff", true)
            .put("cluster.name", config.getClusterName())
            .build();
    }
}

1. Indexing Documents

  Index API旨在为指定的索引创建or更新一个JSON类型的文档,并使之成为可搜索的文档。eg:

public IndexResponse createOrUpdateDocument(String index, IndexType type, String jsonObject) {
    try (TransportClient client = new PreBuiltTransportClient(setting.getSettings())
        .addTransportAddress(setting.getAddress())) {
        return client.prepareIndex(index, Objects.isNull(type) ? null : type.name())
            .setSource(jsonObject, XContentType.JSON).get();
    }
}

以上是我自己在原生的API上再进行了一次封装,以便其它模块的方便使用。从上面的API可以看出,索引,文档内容以及文档类型为必传字段,而文档id(每个文档在es中的唯一标识)为非必传,若我们不传该字段时,es会自动的给我们生成一个(eg:AWvaz8Yop5uxUWtCF426)。
Note: 通常状况下 client.prepareIndex 当es中没有我们指定的索引时,会自动给我们创建。我们也可以通过修改elasticsearch.yml或者直接通过集群的API去禁用该功能,通过将"action.auto_create_index"置为false即可,下面展示的是通过集群API去禁用的代码:

public boolean closeAutoCreateIndexFunction() {
    try (TransportClient client = new PreBuiltTransportClient(setting.getSettings()).addTransportAddress(setting.getAddress())) {
        Settings.Builder autoCreateIndex = Settings.builder().put("action.auto_create_index", false);
        ClusterUpdateSettingsResponse result = client.admin().cluster().prepareUpdateSettings().setPersistentSettings(autoCreateIndex).get();
        return result.getPersistentSettings().getAsBoolean("action.auto_create_index", true);
    }
}

禁用后我们再次测试就会抛出一个找不到索引的异常:

@Test
public void testCreateDocument() {
    Programmer p = Programmer.builder()
        .companyName("alibaba")
        .name("cold_blade")
        .age(31)
        .level(7)
        .salary(20000)
        .build();
    IndexResponse response = documentService.createOrUpdateDocument(Indexes.COMPANY, JSON.toJSONString(p), IndexType.PROGRAMMER);

    Assert.assertEquals(Result.CREATED, response.getResult());
    Assert.assertEquals(Indexes.EMPLOYEE, response.getIndex());
    Assert.assertEquals(IndexType.PROGRAMMER.name(), response.getType());
}

[company] IndexNotFoundException[no such index]
at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:187)
at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:123)
at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteSingleIndex(IndexNameExpressionResolver.java:244)
at org.elasticsearch.action.bulk.TransportBulkAction$ConcreteIndices.resolveIfAbsent(TransportBulkAction.java:494)
at org.elasticsearch.action.bulk.TransportBulkAction$BulkOperation.addFailureIfIndexIsUnavailable(TransportBulkAction.java:448)
...
2. Retrieving and Deleting Documents

  prepareGet,prepareDelete API相对来说比较简单,二者都需要通过索引及其文档的id从集群中检索or删除文档。eg:

public GetResponse getDocument(String index, @Nullable IndexType type, String docId) {
    try (TransportClient client = new PreBuiltTransportClient(setting.getSettings())
        .addTransportAddress(setting.getAddress())) {
        return client.prepareGet(index, Objects.isNull(type) ? null : type.name(), docId).get();
    }
}

public DeleteResponse deleteDocument(String index, IndexType type, String docId) {
    try (TransportClient client = new PreBuiltTransportClient(setting.getSettings())
        .addTransportAddress(setting.getAddress())) {
        return client.prepareDelete(index, type.name(), docId).get();
    }
}

@Test
public void testGet() {
    String docId = "8888";
	// 传type的情形
	GetResponse response = documentService.getDocument(Indexes.EMPLOYEE, IndexType.BOSS, docId);
	Assert.assertTrue(response.isExists());
	
	// 传错误type的情形
	response = documentService.getDocument(Indexes.EMPLOYEE, IndexType.PROGRAMMER, docId);
	Assert.assertFalse(response.isExists());
	
	// 不传type的情形
	response = documentService.getDocument(Indexes.EMPLOYEE, null, docId);
	Assert.assertTrue(response.isExists());
	Boss cold = new JSONObject(response.getSource()).toJavaObject(Boss.class);
	Assert.assertEquals(30, cold.getAge());
}

从测试情况来看 index和docId是关键信息,而type则可传可传,但是如果传了type,则必须保证type的正确性。

3. Querying Indexed Documents

  通过简单的两个example的尝试,我们接下来尝试一个稍微复杂点的API(client.prepareSearch),

// 一个通过年龄范围查询的接口
public SearchResponse rangeAge(int begin, int include) {
    try (TransportClient client = new PreBuiltTransportClient(setting.getSettings())
        .addTransportAddress(setting.getAddress())) {
        return client.prepareSearch()
            // DFS_QUERY_THEN_FETCH 需要对结果进行一个算分的额外操作
            .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
            .setPostFilter(QueryBuilders.rangeQuery("age").from(begin).to(include))
            .execute()
            .actionGet();
    }
}

@Test
public void testSearch() {
    SearchResponse response = documentService.rangeAge(35, 40);
    List<SearchHit> hits = Arrays.asList(response.getHits().getHits());
    Assert.assertFalse(hits.isEmpty());
    Assert.assertTrue(hits.stream()
        .map(hit -> JSON.parseObject(hit.getSourceAsString(), Programmer.class))
        .noneMatch(p -> p.getAge() < 35 || p.getAge() > 40));
}

查询结果对象SearchResponse中包含了很多信息,包括一些统计信息(totalHits等等),其中最重要的数据(数据源)保存在SearchHit中,通过getSourceAsString将结果转换成JSON字串,在通过FastJson转成了我们所定义的对象。这里只是简单的测试了下search接口,其实es还提供了更丰富的支持条件过滤的便使用的对象QueryBuilders,详细可去查看es的源码。

demo 参考


<<  上一篇:Elasticsearch术语
>>  下一篇:Elasticsearch集群基本原理浅析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值