当前位置: 首页 > news >正文

Elasticsearch-java 使用例子

自 Elasticsearch 7.15 版本起,官方推荐使用新的 Java API Client(基于 Jackson),而旧的 High Level REST Client 已被弃用,并在 8.x 版本中移除。

本文将主要介绍新的 Elasticsearch Java API Client 的使用方法。


1. 概述

Elasticsearch Java API Client 是一个强类型的、异步的、高性能的官方客户端。它通过编组(marshalling)/解组(unmarshalling)的方式将 Java 对象与 Elasticsearch 的 JSON 请求和响应进行映射。

核心特点:

  • 强类型:使用类和方法来代表 API 请求和响应,减少错误。

  • 异步优先:基于 CompletableFuture 提供异步操作,同时支持同步阻塞。

  • 与 Jackson 集成:使用 Jackson 进行 JSON 序列化和反序列化。

  • 模块化:每个 Elasticsearch 功能都有独立的依赖模块。


2. 项目设置

2.1 添加 Maven 依赖

在你的 pom.xml 中添加以下依赖:

xml

<dependencies><!-- 客户端核心库 --><dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.13.4</version> <!-- 请使用最新版本 --></dependency><!-- Jackson 依赖,用于 JSON 处理 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.17.2</version> <!-- 确保版本与客户端兼容 --></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.17.2</version></dependency><!-- 底层 HTTP 传输层 (推荐) --><dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.3.1</version></dependency><dependency><groupId>org.apache.httpcomponents.core5</groupId><artifactId>httpcore5</artifactId><version>5.2.5</version></dependency>
</dependencies>
2.2 添加 Gradle 依赖

gradle

dependencies {implementation 'co.elastic.clients:elasticsearch-java:8.13.4'implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2'implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1'
}

3. 初始化客户端

你需要创建一个 ElasticsearchClient 实例,它是所有操作的入口。

3.1 基本初始化(连接到本地集群)

java

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;// 1. 创建底层 Low Level REST Client
RestClient restClient = RestClient.builder(HttpHost.create("http://localhost:9200")) // ES 地址.build();// 2. 使用 Jackson 映射器创建传输层
ElasticsearchTransport transport = new RestClientTransport(restClient,new JacksonJsonpMapper()
);// 3. 创建 API 客户端
ElasticsearchClient client = new ElasticsearchClient(transport);// ... 执行操作// 4. 最后,记得关闭客户端(会关闭底层的 restClient)
// transport.close();
// restClient.close();
3.2 带安全认证的初始化(云服务器或启用安全的集群)

如果你的 Elasticsearch 集群启用了用户名/密码认证或使用 Elastic Cloud:

java

// 创建凭据提供者
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials("elastic", "your_password") // 用户名和密码
);// 创建 Low Level Client
RestClient restClient = RestClient.builder(HttpHost.create("https://your-cluster-url:9200")) // 注意是 https.setHttpClientConfigCallback(httpClientBuilder ->httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)).build();// 后续步骤与上面相同
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);

4. 核心操作示例

4.1 索引文档 (Index)

假设有一个 Product 类:

java

public class Product {private String id;private String name;private double price;// ... 构造方法、Getter 和 Setter
}

方式一:手动指定 ID

java

Product product = new Product("abc123", "Awesome T-Shirt", 29.99);
IndexResponse response = client.index(i -> i.index("products")        // 索引名.id(product.getId())      // 文档 ID.document(product)        // 要索引的文档对象
);System.out.println("Indexed with version: " + response.version());

方式二:自动生成 ID

java

Product product = new Product(null, "Mug", 9.99);
IndexResponse response = client.index(i -> i.index("products").document(product)
);
System.out.println("Indexed with ID: " + response.id()); // 获取自动生成的 ID
4.2 查询文档 (Get)

java

GetResponse<Product> response = client.get(g -> g.index("products").id("abc123"),            // 要查询的文档 IDProduct.class             // 将文档源映射到的目标类
);if (response.found()) {Product product = response.source();System.out.println("Product name: " + product.getName());
} else {System.out.println("Product not found");
}
4.3 搜索文档 (Search)

这是最强大的功能。使用 Lambda 表达式构建复杂的查询。

java

String searchText = "mug";SearchResponse<Product> response = client.search(s -> s.index("products").query(q -> q             // 构建查询.match(t -> t         // 匹配查询.field("name")    // 要搜索的字段.query(searchText) // 搜索词)),Product.class             // 命中结果映射到的类
);// 处理结果
System.out.println("Total hits: " + response.hits().total().value());
for (Hit<Product> hit : response.hits().hits()) {Product product = hit.source();System.out.println("Found product: " + product.getName() + " (score: " + hit.score() + ")");
}
4.4 更新文档 (Update)

java

// 使用脚本更新价格
UpdateResponse<Product> response = client.update(u -> u.index("products").id("abc123").script(s -> s.inline(in -> in.source("ctx._source.price += params.price_increment") // Painless 脚本.params("price_increment", JsonData.of(5.0))           // 脚本参数)),Product.class // 返回更新后的文档(需要设置 `_source` 字段)
);// 或者使用 doc 进行部分更新(更常见)
Map<String, Object> updatedFields = new HashMap<>();
updatedFields.put("price", 35.99);client.update(u -> u.index("products").id("abc123").doc(updatedFields), // 直接提供要更新的字段映射Void.class           // 如果不关心返回的文档,可以使用 Void
);
4.5 删除文档 (Delete)

java

DeleteResponse response = client.delete(d -> d.index("products").id("abc123")
);if (response.result() == Result.Deleted) {System.out.println("Document deleted successfully");
}

5. 异常处理

客户端操作可能会抛出异常,建议进行捕获和处理。

java

import co.elastic.clients.elasticsearch._types.ElasticsearchException;try {GetResponse<Product> response = client.get(g -> g.index("products").id("non-existent-id"),Product.class);// ... 处理响应
} catch (ElasticsearchException e) {// ES 返回的错误(如 404 Not Found)System.err.println("Elasticsearch exception: " + e.getMessage());// e.response().error().rootCause().get(0).reason();
} catch (IOException e) {// 网络 IO 错误System.err.println("IO exception: " + e.getMessage());
}

6. 同步 vs. 异步操作

上面的例子都是同步的(会阻塞当前线程)。客户端也天然支持异步操作。

异步示例:

java

// 返回一个 CompletableFuture
CompletableFuture<SearchResponse<Product>> future = client.search(s -> s.index("products").query(q -> q.matchAll(m -> m)),Product.class
);// 使用 Future 的 thenAccept 方法处理结果(非阻塞)
future.thenAccept(response -> {System.out.println("Total hits: " + response.hits().total().value());// 注意:此回调可能在非主线程中执行
}).exceptionally(e -> {System.err.println("Search failed: " + e.getMessage());return null;
});// 主线程可以继续做其他事情...
// 如果需要等待结果,可以使用 future.get()

7. 最佳实践和提示

  1. 重用客户端ElasticsearchClient 是线程安全的,非常重量级。应该在应用程序中作为单例创建和重用,而不是为每个请求创建一个新实例。

  2. 正确关闭:在应用程序关闭时(例如,使用 JVM 的 shutdown hook),务必调用 transport.close() 或 restClient.close() 来释放资源。

  3. 处理复杂 JSON:如果你的文档包含复杂的嵌套结构或特殊类型(如 Date),可能需要配置自定义的 Jackson ObjectMapper 并传递给 JacksonJsonpMapper 构造函数。

  4. 查看官方文档:API 非常庞大,本文只涵盖了基础。始终将 官方文档 作为最权威的参考。

  5. 使用 IDE 自动补全:由于是强类型和流式 API,IDE 的自动补全功能是你的好朋友,可以帮你发现所有可用的选项和方法。


文章转载自:

http://73fo8s1V.gjLxn.cn
http://7BWHfXD6.gjLxn.cn
http://pmdPzW0R.gjLxn.cn
http://DFu8hwCk.gjLxn.cn
http://crFxPBsk.gjLxn.cn
http://VKXcpqB3.gjLxn.cn
http://5Ac8pXBC.gjLxn.cn
http://TqHFDUOw.gjLxn.cn
http://ET0cpR58.gjLxn.cn
http://vp7XP5nk.gjLxn.cn
http://n8YcZpDB.gjLxn.cn
http://E4l6fIjI.gjLxn.cn
http://5L15Lp3F.gjLxn.cn
http://yMYOEcYf.gjLxn.cn
http://UcwE164Z.gjLxn.cn
http://5oKwEkZd.gjLxn.cn
http://2TuhJQL1.gjLxn.cn
http://HBNU2QOu.gjLxn.cn
http://ZusNtkkp.gjLxn.cn
http://Yjx0gvpl.gjLxn.cn
http://b5IYGvMg.gjLxn.cn
http://8TG1Lqvo.gjLxn.cn
http://3Nobs62m.gjLxn.cn
http://nR1ojjFv.gjLxn.cn
http://0Eqhe5eC.gjLxn.cn
http://PMGz2CNU.gjLxn.cn
http://0tGzaTbs.gjLxn.cn
http://uUuaWkxx.gjLxn.cn
http://eiDgq4h5.gjLxn.cn
http://X5cSIjhP.gjLxn.cn
http://www.dtcms.com/a/368311.html

相关文章:

  • 我改写的二分法XML转CSV文件程序速度追上了张泽鹏先生的
  • GPU测速方法
  • OpenCV C++ 色彩空间详解:转换、应用与 LUT 技术
  • 前端笔记2025
  • 跨境电商:如何提高电商平台数据抓取效率?
  • python + Flask模块学习 2 接收用户请求并返回json数据
  • K8S-Pod(上)
  • 【代码随想录day 23】 力扣 93.复原IP地址
  • 数据结构:栈和队列(下)
  • SAP官方授权供应商名单2025
  • 结构体简介
  • UE4 Mac构建编译报错 no template named “is_void_v” in namespace “std”
  • 嵌入式系统学习Day30(udp)
  • 【Linux】Linux进程状态和僵尸进程:一篇看懂“进程在忙啥”
  • 理解UE4中C++17的...符号及enable_if_t的用法及SFINAE思想
  • 某头部能源集团“数据治理”到“数智应用”跃迁案例剖析
  • 阿里云服务器配置ssl-docker nginx
  • 2025年COR SCI2区,基于近似细胞分解的能源高效无人机路径规划问题用于地质灾害监测,深度解析+性能实测
  • 实战案例:数字孪生+可视化大屏,如何高效管理智慧能源园区?
  • 容器的定义及工作原理
  • 【Python - 类库 - BeautifulSoup】(01)“BeautifulSoup“使用示例
  • 神经网络之深入理解偏置
  • 三、神经网络
  • 仓颉编程语言青少年基础教程:布尔类型、元组类型
  • UC Berkeley 开源大世界模型(LWM):多模态大模型领域世界模型技术新进展
  • 一次由CellStyle.hashCode值不一致引发的HashMap.get返回null问题排查
  • 【Java鱼皮】智能协同云图库项目梳理
  • 固定资产报废在BPM或OA中审批,再通过接口传到SAP
  • Redis-持久化
  • 寻找AI——初识3D建模AI