• 深入了解Elasticsearch的CRUD:ES Java API之增删改查


    在基本了解并在Kibana Dev Tools控制台操作Elasticsearch的查询语法之后,是时候在实际应用中使用ES了。那么怎么在Java中使用ES呢?

    可以有下面几种方式来实现:

    • Transport Client
    • Java High Level REST Client
    • Spring Data Elasticsearch

    TransportClient 可用于老版本的Elasticsearch;新版本建议使用 Java High Level REST Client (向下兼容);当然还可以使用Spring Data提供的 Spring Data Elasticsearch 。

    本文先只介绍一下 Transport Client API,后面慢慢来 REST Client 和 Spring Data Elasticsearch 。

    Transport Client

    注意:在7.0.0中弃用。不推荐使用TransportClient,而推荐使用Java High Level REST Client,并将在Elasticsearch 8.0中将其删除。

    Elasticsearch 8.x版本将会删除 TransportClient 。这里为什么还要介绍一下它的API呢?毕竟有些老铁用的还是以前的版本,而且API很多地方是相通的,那就多学习一点吧!

    引入jar包

    1. <pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><dependency>
    2. <groupId>org.elasticsearch.clientgroupId>
    3. <artifactId>transportartifactId>
    4. <version>7.9.0version>
    5. dependency>

    注意版本号,一定要和你安装的Elasticsearch的版本号一致。

    创建到ES的连接

    必须得先连接到ES才能进行一系列的API测试,连接的代码如下:

    1. class="prettyprint hljs go" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">// 创建连接
    2. TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
    3. .addTransportAddress(
    4. new TransportAddress(
    5. InetAddress.getByName("localhost"), 9300));
    6. //一系列操作...
    7. //关闭连接
    8. client.close();

    可以看到, TransportClient 是deprecated,弃用了,我用的是ES 7.9版本,它在7.0.0中被弃用。

    注意:

    1. InetAddress.getByName("localhost"), 9300) 这里绑定的端口 9300 是通讯端口,不是服务端口(服务端口是9200)
    2. 如果使用与 Elasticsearch 不同的集群名称,则必须设置集群名称:
    1. "prettyprint hljs dockerfile" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Settings settings = Settings.builder()
    2. .put("cluster.name", "myClusterName").build();
    3. TransportClient client = new PreBuiltTransportClient(settings);
    4. //Add transport addresses and do something with the client...

    比如我的:

    单节点ES默认的集群名称就是 elasticsearch 。

    Index API

    索引API允许将输入的JSON文档索引到特定索引中并使之可搜索。

    生成JSON文档

    生成JSON文档有很多种方法,比如:

    • 手动构造
    1. <pre class="prettyprint hljs vbscript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">String json = "{" +
    2. "\"user\":\"kimchy\"," +
    3. "\"postDate\":\"2013-01-30\"," +
    4. "\"message\":\"trying out Elasticsearch\"" +
    5. "}";
    • 使用Map
    1. class="prettyprint hljs javascript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Map<String, Object> json = new HashMap<String, Object>();
    2. json.put("user","kimchy");
    3. json.put("postDate",new Date());
    4. json.put("message","trying out Elasticsearch");

    Map是一个key:values对集合。它可以表示一个JSON结构。

    • Jackson

    可以使用Jackson将bean序列化为JSON。

    1. "prettyprint hljs verilog" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import com.fasterxml.jackson.databind.*;
    2. // instance a json mapper
    3. ObjectMapper mapper = new ObjectMapper(); // create once, reuse
    4. // generate json
    5. byte[] json = mapper.writeValueAsBytes(yourbeaninstance);
    • fastjson

    com.alibaba.fastjson.JSONObject

    它的转换方法,包括Java对象转成JSON串、JSON对象,JSON串转成java对象、JSON对象,JSON对象转换Java对象、JSON串等。

    1. class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">String stuString = "{\"age\":2,\"name\":\"公众号行百里er\",\"sex\":\"m\"}";
    2. //JSON字符串转换成JSON对象
    3. JSONObject jsonObject1 = JSONObject.parseObject(stuString);
    • 等等

    当然,Elasticsearch 也提供了内置的帮助器以生成JSON内容:

    1. class="prettyprint hljs vbscript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">XContentBuilder builder = jsonBuilder()
    2. .startObject()
    3. .field("user", "kimchy")
    4. .field("postDate", new Date())
    5. .field("message", "trying out Elasticsearch")
    6. .endObject()

    增删改查API

    Create 创建索引、文档相关API

    向索引添加文档,如果索引不存在,则该API会自动给我们创建索引

    1. class="prettyprint hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@Test
    2. @SneakyThrows
    3. void esCRUD() {
    4. // 创建连接
    5. TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
    6. .addTransportAddress(
    7. new TransportAddress(
    8. InetAddress.getByName("localhost"), 9300));
    9. //增
    10. //create(client);
    11. //查
    12. //get(client);
    13. //getAll(client);
    14. //改
    15. //update(client);
    16. //删
    17. delete(client);
    18. }
    19. @SneakyThrows
    20. void create(TransportClient client){
    21. for (int i = 0; i < 5; i++) {
    22. XContentBuilder builder = XContentFactory.jsonBuilder()
    23. .startObject()
    24. .field("empName", "name" + i)
    25. .field("age", new Random().nextInt(100))
    26. .field("createTime", new Date())
    27. .endObject();
    28. IndexResponse response = client.prepareIndex("emp", "_doc", String.valueOf(i))
    29. .setSource(builder)
    30. .get();
    31. // //还可以不指定id
    32. // IndexResponse response = client.prepareIndex("emp", "_doc")
    33. // .setSource(builder)
    34. // .get();
    35. System.out.println(response.getResult());
    36. }
    37. }

    这里我用prepareIndex指定id和不指定id分别执行了一遍,所以应该有10条文档产生。

    通过Kibana控制台验证一下执行结果:

    结果是执行成功的!

    正好,用查询API来验证一下。

    GET API 查询单个、所有文档相关API

    代码生成的时候,又生成id为0~4的文档,就查一下id为3的吧先:

    1. class="prettyprint hljs typescript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private void get(TransportClient client) {
    2. GetResponse response = client.prepareGet("emp", "_doc", "3").get();
    3. String index = response.getIndex();//获取索引名称
    4. String type = response.getType();//获取索引类型
    5. String id = response.getId();//获取索引id
    6. System.out.println("index:" + index);
    7. System.out.println("type:" + type);
    8. System.out.println("id:" + id);
    9. System.out.println(response.getSourceAsString());
    10. }

    执行成功!

    查询所有的API试一下:

    1. class="prettyprint hljs vbscript" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private void getAll(TransportClient client) {
    2. SearchResponse response = client.prepareSearch("emp").get();
    3. SearchHits searchHits = response.getHits();
    4. SearchHit[] hits = searchHits.getHits();
    5. for (SearchHit hit : hits) {
    6. String res = hit.getSourceAsString();
    7. System.out.println("res" + res);
    8. }
    9. }

    OK,成功查询出所有文档。

    这里可以对比Kibana Dev Tools控制台返回的json结果,

    1. class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">{
    2. "took" : 134,
    3. "timed_out" : false,
    4. "_shards" : {
    5. "total" : 1,
    6. "successful" : 1,
    7. "skipped" : 0,
    8. "failed" : 0
    9. },
    10. "hits" : {
    11. "total" : {
    12. "value" : 10,
    13. "relation" : "eq"
    14. },
    15. "max_score" : 1.0,
    16. "hits" : [
    17. {
    18. "_index" : "emp",
    19. "_type" : "_doc",
    20. "_id" : "ze2qFnQBZf6fz3EOVZFP",
    21. "_score" : 1.0,
    22. "_source" : {
    23. "empName" : "name0",
    24. "age" : 35,
    25. "createTime" : "2020-08-22T14:54:54.999Z"
    26. }
    27. },
    28. // 中间的结果略...
    29. {
    30. "_index" : "emp",
    31. "_type" : "_doc",
    32. "_id" : "4",
    33. "_score" : 1.0,
    34. "_source" : {
    35. "empName" : "name4",
    36. "age" : 56,
    37. "createTime" : "2020-08-22T15:05:58.480Z"
    38. }
    39. }
    40. ]
    41. }
    42. }

    Java API的一些方法名和ES查询结果JSON先关字段一般能对的上,如果平时控制台操作比较熟悉的话,再来使用API其实很简单了!

    Update API

    修改id为3的记录,将其name改为鲁班7号:

    1. class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private void update(TransportClient client) {
    2. try {
    3. UpdateResponse response = client.prepareUpdate("emp", "_doc", "3")
    4. .setDoc(XContentFactory.jsonBuilder()
    5. .startObject()
    6. .field("name", "鲁班7号")
    7. .endObject())
    8. .get();
    9. System.out.println(response.getResult());
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. }
    13. }

    验证一下:

    Delete API

    删除id为3的文档记录:

    1. class="prettyprint hljs cs" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private void delete(TransportClient client) {
    2. DeleteResponse response = client.prepareDelete("emp", "_doc", "3").get();
    3. System.out.println(response.getResult());
    4. }
  • 相关阅读:
    requests库中解决字典值中列表在URL编码时的问题
    【算法】数组常见算法
    ubuntu20.04使用kubeadm安装kubernetes1.24.4
    【Obsidian样式】修改文件夹名称和文件名称前的图标
    Windows系统配置CUDA编程环境
    代码质量与安全 | “吃狗粮”能够影响到代码质量?来了解一下!
    从开店营销到智能化私域运营,有赞发布人工智能引擎Jarvis
    基于阿里云GPU云服务器的AIACC助力UC搜索业务性能提效380%,每年节省数千万成本
    自学雅思的教程
    typescript+webpack构建一个js库
  • 原文地址:https://blog.csdn.net/Java_ttcd/article/details/126361777