• 实用篇-ES-RestClient操作文档


    一、RestClient案例准备

    对es概念不熟悉的话,先去看上面的 '实用篇-ES-索引库和文档',不建议基础不牢就直接往下学

    ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求来发送给ES。

    官方文档地址: https://www.elastic.co/guide/en/elasticsearch/client/index.html

    下面就使用java程序进行操作es,不再像上面那样使用浏览器页面进行操作es

    在下面会逐步完成一个案例: 下载提供的hotel-demo.zip压缩包,解压后是hotel-demo文件夹,是一个java项目工程文件,按照条件创建索引库,索引库名为hotel,mapping属性根据数据库结构定义。还要下载一个tb_hotel.sql文件,作为数据库数据

    hotel-demo.zip下载:https://cowtransfer.com/s/36ac0a9f9d9043
    tb_hotel.sql下载: https://cowtransfer.com/s/716f049850a849

    第一步: 把tb_hotel.sql文件导入进你的数据库

    第二步:idea打开解压后的文件

    第三步:在application.yml中配置正确的信息

    二、hotel数据结构分析

    在es中,mapping要考虑的问题: 字段名、数据类型、是否参与搜索、是否分词、如果分词那么分词器是什么。

    我们刚刚在mysql导入了tb_hotel.sql,里面有很多数据,我们需要基于这些数据结构,去分析并尝试编写对应的es的mapping映射

    先看mysql中的数据类型(已有),如下

    根据mysql的数据类型等信息,编写es(没有,自己对着上面的sql写的)。注意经纬度在es里面是geo_point类型,且经纬度是写在一起的

    1. PUT /hotel
    2. {
    3. "mappings": {
    4. "properties": {
    5. "id":{
    6. "type": "keyword"
    7. },
    8. "name":{
    9. "type": "text",
    10. "analyzer": "ik_max_word"
    11. },
    12. "address":{
    13. "type": "keyword",
    14. "index":false
    15. },
    16. "price":{
    17. "type": "integer"
    18. },
    19. "score":{
    20. "type": "integer"
    21. },
    22. "brand":{
    23. "type": "keyword"
    24. },
    25. "city":{
    26. "type": "keyword"
    27. },
    28. "starName":{
    29. "type": "keyword"
    30. },
    31. "business":{
    32. "type": "keyword"
    33. },
    34. "location":{
    35. "type": "geo_point"
    36. },
    37. "pic":{
    38. "type":"keyword",
    39. "index": false
    40. }
    41. }
    42. }
    43. }

    可以看到name,brand,score,city,starName等字段都要参与搜索,也就是用户可能根据多个关键字搜,查询条件是多个值,这时候可以用es提供的copy_to属性,把这些字段都拷贝到这个字段中,就可以实现在一个字段中搜到多个字段的内容了

    下面演示把名字(name)、品牌(brand)和商圈(business)三个字段拷贝到all字段,代码如下

    1. PUT /hotel
    2. {
    3. "mappings": {
    4. "properties": {
    5. "id":{
    6. "type": "keyword"
    7. },
    8. "name":{
    9. "type": "text",
    10. "analyzer": "ik_max_word",
    11. "copy_to": "all"
    12. },
    13. "address":{
    14. "type": "keyword",
    15. "index":false
    16. },
    17. "price":{
    18. "type": "integer"
    19. },
    20. "score":{
    21. "type": "integer"
    22. },
    23. "brand":{
    24. "type": "keyword",
    25. "copy_to": "all"
    26. },
    27. "city":{
    28. "type": "keyword"
    29. },
    30. "starName":{
    31. "type": "keyword"
    32. },
    33. "business":{
    34. "type": "keyword",
    35. "copy_to": "all"
    36. },
    37. "location":{
    38. "type": "geo_point"
    39. },
    40. "pic":{
    41. "type":"keyword",
    42. "index": false
    43. },
    44. "all":{
    45. "type": "text",
    46. "analyzer": "ik_max_word"
    47. }
    48. }
    49. }
    50. }

    三、初始化RestClient

    操作主要是在idea的hotel-demo项目进行,hotel-demo项目(不是springcloud项目,只是springboot项目)是前面 '1. RestClient案例准备',跳过的可回去补

    第一步: 在hotel-demo项目的pom.xml添加如下

    1. <properties>
    2. <java.version>1.8java.version>
    3. <elasticsearch.version>7.12.1elasticsearch.version>
    4. properties>
    5. <dependency>
    6. <groupId>org.elasticsearch.clientgroupId>
    7. <artifactId>elasticsearch-rest-high-level-clientartifactId>
    8. <version>7.12.1version>
    9. dependency>

    第二步: 在hotel-demo项目的src/test/java/cn.itcast.hotel目录新建HotelIndexTest类,写入如下

    1. package cn.itcast.hotel;
    2. import org.apache.http.HttpHost;
    3. import org.elasticsearch.client.RestClient;
    4. import org.elasticsearch.client.RestClientBuilder;
    5. import org.elasticsearch.client.RestHighLevelClient;
    6. import org.junit.jupiter.api.AfterEach;
    7. import org.junit.jupiter.api.BeforeEach;
    8. import org.junit.jupiter.api.Test;
    9. import java.io.IOException;
    10. public class HotelIndexTest {
    11. private RestHighLevelClient client;
    12. @Test
    13. void init(){
    14. System.out.println(client);
    15. }
    16. @BeforeEach
    17. void setUp(){
    18. this.client = new RestHighLevelClient(RestClient.builder(
    19. //指定你Centos7部署的es的主机地址
    20. HttpHost.create("http://192.168.229.129:9200")
    21. ));
    22. }
    23. @AfterEach
    24. void tearDown() throws IOException {
    25. this.client.close();
    26. }
    27. }

    运行init方法,可以看到client的信息打印出来,表示初始化成功 

    四、创建索引库

    不是通过kibana的浏览器控制台,通过DSL语句来进行操作es,在es里面创建索引库

    而是通过上一节初始化的RestClient对象,在Java里面去操作es,创建es的索引库。根本不需要kibana做中间者

    第一步: 在src/main/java/cn.itcast.hotel目录新建constants.HotelConstants类,里面写DSL语句,如下

    其中长长的字符串就是我们在前面 '2. hotel数据结构分析' 里面写的。忘了怎么写出来的,可以回去看看

    1. package cn.itcast.hotel.constants;
    2. public class HotelConstants {
    3. public static final String MAPPING_TAMPLATE = "{\n" +
    4. " \"mappings\": {\n" +
    5. " \"properties\": {\n" +
    6. " \"id\":{\n" +
    7. " \"type\": \"keyword\"\n" +
    8. " },\n" +
    9. " \"name\":{\n" +
    10. " \"type\": \"text\",\n" +
    11. " \"analyzer\": \"ik_max_word\",\n" +
    12. " \"copy_to\": \"all\"\n" +
    13. " },\n" +
    14. " \"address\":{\n" +
    15. " \"type\": \"keyword\",\n" +
    16. " \"index\":false\n" +
    17. " },\n" +
    18. " \"price\":{\n" +
    19. " \"type\": \"integer\"\n" +
    20. " },\n" +
    21. " \"score\":{\n" +
    22. " \"type\": \"integer\"\n" +
    23. " },\n" +
    24. " \"brand\":{\n" +
    25. " \"type\": \"keyword\",\n" +
    26. " \"copy_to\": \"all\"\n" +
    27. " },\n" +
    28. " \"city\":{\n" +
    29. " \"type\": \"keyword\"\n" +
    30. " },\n" +
    31. " \"starName\":{\n" +
    32. " \"type\": \"keyword\"\n" +
    33. " },\n" +
    34. " \"business\":{\n" +
    35. " \"type\": \"keyword\",\n" +
    36. " \"copy_to\": \"all\"\n" +
    37. " },\n" +
    38. " \"location\":{\n" +
    39. " \"type\": \"geo_point\"\n" +
    40. " },\n" +
    41. " \"pic\":{\n" +
    42. " \"type\":\"keyword\",\n" +
    43. " \"index\": false\n" +
    44. " },\n" +
    45. " \"all\":{\n" +
    46. " \"type\": \"text\",\n" +
    47. " \"analyzer\": \"ik_max_word\"\n" +
    48. " }\n" +
    49. " }\n" +
    50. " }\n" +
    51. "}";
    52. }

    第二步: 在hotel-demo项目的HotelIndexTest类,添加如下

    1. @Test
    2. void testCreateHotelIndex() throws IOException {
    3. //创建Request对象
    4. CreateIndexRequest request = new CreateIndexRequest("hotel");
    5. //请求参数,MAPPING_TEMPLATE是静态常量字符串,内容是创建索引库的DSL语句
    6. request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
    7. //发起请求
    8. client.indices().create(request, RequestOptions.DEFAULT);
    9. }

    第三步: 确保下面的服务你都在Centos7里面启动了

    1. systemctl start docker # 启动docker服务
    2. docker restart es #启动elasticsearch容器
    3. docker restart kibana #启动kibana容器

    第四步: 验证。运行HotelIndexTest类的testCreateHotelIndex测试方法

    第五步: 验证,浏览器打开http://192.168.229.129:5601

    五、删除和判断索引库

    1、删除索引库。在hotel-demo项目的HotelIndexTest类,添加如下。然后运行testDeleteHotelIndex方法

    1. @Test
    2. void testDeleteHotelIndex() throws IOException {
    3. DeleteIndexRequest request = new DeleteIndexRequest("hotel");
    4. client.indices().delete(request,RequestOptions.DEFAULT);
    5. }

     

    2. 判断索引库是否存在,刚才我们已经运行过删除索引库了,现在我们来写一个测试来判断索引库是否存在

    1. @Test
    2. void testExistsHotelIndex() throws IOException {
    3. GetIndexRequest request = new GetIndexRequest("hotel");
    4. boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    5. System.err.println(exists?"索引库存在":"索引库不存在");
    6. }

    六、新增文档

    案例: 去数据库查询酒店数据,把查询到的结果导入到hotel索引库(上一节我们已经创建一个名为hotel的索引库),实现酒店数据的增删改查

    简单说就是先去数据查酒店数据,把结果转换成索引库所需要的格式(新增文档的DSL语法)然后写到索引库,然后在索引库对这些酒店数据进行增删改查

    第一步:在HotelIndexTest写入如下

    1. package cn.itcast.hotel;
    2. import cn.itcast.hotel.constants.HotelConstants;
    3. import cn.itcast.hotel.pojo.Hotel;
    4. import cn.itcast.hotel.pojo.HotelDoc;
    5. import cn.itcast.hotel.service.IHotelService;
    6. import com.alibaba.fastjson.JSON;
    7. import org.apache.http.HttpHost;
    8. import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
    9. import org.elasticsearch.action.delete.DeleteRequest;
    10. import org.elasticsearch.action.index.IndexRequest;
    11. import org.elasticsearch.client.RequestOptions;
    12. import org.elasticsearch.client.RestClient;
    13. import org.elasticsearch.client.RestClientBuilder;
    14. import org.elasticsearch.client.RestHighLevelClient;
    15. import org.elasticsearch.client.indices.CreateIndexRequest;
    16. import org.elasticsearch.client.indices.GetIndexRequest;
    17. import org.elasticsearch.common.xcontent.XContentType;
    18. import org.junit.jupiter.api.AfterEach;
    19. import org.junit.jupiter.api.BeforeEach;
    20. import org.junit.jupiter.api.Test;
    21. import org.springframework.beans.factory.annotation.Autowired;
    22. import org.springframework.boot.autoconfigure.SpringBootApplication;
    23. import org.springframework.boot.test.context.SpringBootTest;
    24. import java.io.IOException;
    25. @SpringBootTest
    26. public class HotelIndexTest {
    27. private RestHighLevelClient client;
    28. @Autowired
    29. private IHotelService hotelService;
    30. @Test
    31. void init(){
    32. System.out.println(client);
    33. }
    34. @Test
    35. void testCreateHotelIndex() throws IOException {
    36. //创建Request对象
    37. CreateIndexRequest request = new CreateIndexRequest("hotel");
    38. //请求参数,MAPPING_TEMPLATE是静态常量字符串,内容是创建索引库的DSL语句
    39. request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
    40. //发起请求
    41. client.indices().create(request, RequestOptions.DEFAULT);
    42. }
    43. @Test
    44. void testDeleteHotelIndex() throws IOException {
    45. DeleteIndexRequest request = new DeleteIndexRequest("hotel");
    46. client.indices().delete(request,RequestOptions.DEFAULT);
    47. }
    48. @Test
    49. void testExistsHotelIndex() throws IOException {
    50. GetIndexRequest request = new GetIndexRequest("hotel");
    51. boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    52. System.err.println(exists?"索引库存在":"索引库不存在");
    53. }
    54. @BeforeEach
    55. void setUp(){
    56. this.client = new RestHighLevelClient(RestClient.builder(
    57. //指定你Centos7部署的es的主机地址
    58. HttpHost.create("http://192.168.229.129:9200")
    59. ));
    60. }
    61. @AfterEach
    62. void tearDown() throws IOException {
    63. this.client.close();
    64. }
    65. @Test
    66. void testAddDocument() throws IOException {
    67. //根据id查询酒店数据
    68. //注意数据库中bigint类型对应java中的long类型
    69. Hotel hotel = hotelService.getById(60223L);
    70. //转换为文档类型
    71. HotelDoc hotelDoc = new HotelDoc(hotel);
    72. //准备Request对象
    73. IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
    74. //准备Json文档
    75. request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
    76. //发送请求
    77. client.index(request,RequestOptions.DEFAULT);
    78. }
    79. }

    主要是新增这个方法 

    1. @Test
    2. void testAddDocument() throws IOException {
    3. //根据id查询酒店数据
    4. //注意数据库中bigint类型对应java中的long类型
    5. Hotel hotel = hotelService.getById(60223L);
    6. //转换为文档类型
    7. HotelDoc hotelDoc = new HotelDoc(hotel);
    8. //准备Request对象
    9. IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
    10. //准备Json文档
    11. request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
    12. //发送请求
    13. client.index(request,RequestOptions.DEFAULT);
    14. }

    第二步:文档新增成功,我们去浏览器查询一下 

    七、查询文档

    不管我们学习什么样的文档操作,java中的代码和DSL中的语句非常相似,所以我们可以类比着DSL语句来编写java代码

    具体操作如下,我们查询刚才添加的id为60223的文档信息

    1. @Test
    2. void testGetDocumentById() throws IOException {
    3. //创建request对象
    4. GetRequest request = new GetRequest("hotel","60223");
    5. //发送请求
    6. GetResponse response = client.get(request,RequestOptions.DEFAULT);
    7. //解析结果
    8. String res = response.getSourceAsString();
    9. System.out.println(res);
    10. }

    八、更新文档

    具体操作,把id为60223的文档信息更新一下,名字和城市

    第一步:写入此方法,并运行 

    1. @Test
    2. void testUpdateDocumentById() throws IOException {
    3. //创建Request对象
    4. UpdateRequest request = new UpdateRequest("hotel","60223");
    5. //准备参数,每两个参数为一对key value
    6. request.doc(
    7. "name","上海梅赛德斯奔驰文化中心",
    8. "city","阿布扎比"
    9. );
    10. //更新文档
    11. client.update(request,RequestOptions.DEFAULT);
    12. }

    第二步:测试是否更新,在浏览器中Get请求

     九、删除文档

    经过以上类比,我们不难写出删除文档的代码

    具体操作,删除id为60223的文档信息

    1. @Test
    2. void testDeleteDocumentById() throws IOException {
    3. //创建Request对象
    4. DeleteRequest request = new DeleteRequest("hotel","60223");
    5. //删除文档
    6. client.delete(request,RequestOptions.DEFAULT);
    7. }

     测试如下

    十、批量导入文档

    我们一直都是操作一条id为60223的文档(相当于数据库表的某一行)。我们如何把mysql的更多数据导入进es的索引库(相当于mysql的表)呢,下面就来学习批量把文档导入进索引库

    1. 思路:
    2. 1、利用mybatis-plus把MySQL中的酒店数据查询出来
    3. 2、将查询到的酒店数据转换为文档类型的数据
    4. 3、利用RestClient中bulk批处理方法,实现批量新增文档

    第一步: 在HotelDocumentTest类,添加如下

    1. @Test
    2. void testBulkRequest() throws IOException {
    3. //mp查出数据库中所有的信息
    4. List hotelList = hotelService.list();
    5. //转化为hotelDoc
    6. List hotelDocList = hotelList.stream()
    7. .map(new Function() {
    8. @Override
    9. public HotelDoc apply(Hotel hotel) {
    10. HotelDoc hotelDoc = new HotelDoc(hotel);
    11. return hotelDoc;
    12. }
    13. }).collect(Collectors.toList());
    14. //创建Bulk请求
    15. BulkRequest bulkRequest = new BulkRequest();
    16. hotelDocList.forEach(hotelDoc -> bulkRequest
    17. .add(new IndexRequest("hotel").id(hotelDoc.getId().toString())
    18. .source(JSON.toJSONString(hotelDoc),XContentType.JSON)));
    19. //发送bulk请求
    20. client.bulk(bulkRequest, RequestOptions.DEFAULT);
    21. }
    22. }

    第二步:浏览器批量查询

  • 相关阅读:
    Win11运行虚拟机死机了?Win11运行VMware虚拟机崩溃的解决方法
    【java】BigDecimal 正确声明方式
    VoLTE端到端业务详解 | 空口主要特性功能
    数据结构与算法之LeetCode-515. 在每个树行中找最大值(DFS,BFS)
    Clion 中文输入的问题
    【MySQL】数据类型(二)
    005 gtsam/examples/easyPoint2KalmanFilter.cpp
    tkinter控件样式
    C语言进阶C++知识点补充(二)
    【体系结构】计算机体系结构知识点清单
  • 原文地址:https://blog.csdn.net/m0_63732435/article/details/134407242