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

[微服务]elasticsearc客服端操作

客户端初始化

Elasticsearch目前最新版本是8.0,其java客户端有很大变化。不过大多数企业使用的还是8以下版本,所以我们选择使用早期的lavaRestClient客户端来学习。

官方文档地址: Elasticsearch Clients | Elastic

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

分为三步:

1)在item-service模块中引入esRestHighLevelClient依赖:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

2)因为SpringBoot默认的ES版本是7.17.10,所以我们需要覆盖默认的ES版本:

<properties>
      <elasticsearch.version>7.12.1</elasticsearch.version>
  </properties>

3)初始化RestHighLevelClient:

初始化的语法如下:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        HttpHost.create("http://192.168.150.101:9200")
));

为了单元测试方便,我们创建一个测试类IndexTest,然后将初始化的代码编写在@BeforeEach方法中:

public class ElasticTest {

    private RestHighLevelClient client;

    @Test
    void test() {
        System.out.println("client =" + client);
    }

    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://...:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

启动测试

商品表Mapping映射

我们要实现商品搜索,那么索引库的字段肯定要满足页面搜索的需求:

# 商品索引库
PUT /hmall
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "name": {
        "type": "text",
        "analyzer": ":ik_smart" # 分词器类型
      },
      "price": {
        "type": "integer"
      },
      "image": {
        "type": "keyword",
        "index": false # 不需要参与搜索
      },
      "category": {
        "type": "keyword"
      },
      "brabd": {
        "type": "keyword"
      },
      "sold": {
        "type": "integer"
      },
      "commentCount": {
        "type": "integer",
        "index": false
      }
      "isAD": {
        "type": "boolean"
      },
      "updateTime": {
        "type": "date"
      }
    }
  }

索引库操作

创建索引库的JavaAPI与Restful接口API对比:

删除索引库

查询索引库

代码示例

public class ElasticIndexTest {

    private RestHighLevelClient client;

    @Test
    void test() {
        System.out.println("client =" + client);
    }

    @Test
    void testCreateIndex() throws IOException {
        // 1. 准备Request对象
        CreateIndexRequest request = new CreateIndexRequest("items");
        // 2. 准备请求参数
        //  request.source(请求体数据, 请求体类型);
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        // 3. 发送请求
        // client.indices() 得到索引库操作对象
        // client.indices().create(请求参数, 请求可选项)
        // RequestOptions.DEFAULT 默认的请求选项
        client.indices().create(request, RequestOptions.DEFAULT);
    }

    @Test
    void testGetIndex() throws IOException {
        // 1. 准备Request对象
        GetIndexRequest request = new GetIndexRequest("items");
        // 2. 发送请求
        // 查询索引库, 返回索引库信息
        //  GetIndexResponse res = client.indices().get(request, RequestOptions.DEFAULT);
        // 查询索引库是否存在, 返回布尔值
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println("exists = " + exists);
    }

    @Test
    void testDelIndex() throws IOException {
        // 1. 准备Request对象
        DeleteIndexRequest request = new DeleteIndexRequest("items");
        // 2. 发送请求
        client.indices().delete(request, RequestOptions.DEFAULT);
    }

    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }

    private static final String MAPPING_TEMPLATE = "{\n" +
            "  \"mappings\": {\n" +
            "    \"properties\": {\n" +
            "      \"id\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"name\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_smart\"\n" +
            "      },\n" +
            "      \"price\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"image\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"category\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"brabd\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"sold\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"commentCount\": {\n" +
            "        \"type\": \"integer\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"isAD\": {\n" +
            "        \"type\": \"boolean\"\n" +
            "      },\n" +
            "      \"updateTime\": {\n" +
            "        \"type\": \"date\"\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";
}

文档操作

1. 新增文档

  1. 索引库准备好以后,就可以操作文档了。为了与索引库操作分离,我们创建一个测试类,做两件事情:
  • 初始化RestHighLevelClient
  • 我们的商品数据在数据库,需要利用IHotelService去查询,所以注入这个接口

@SpringBootTest(properties = "spring.profiles.active=local")
public class ElasticDocumentTest {

    private RestHighLevelClient client;

    // 这个接口查询数据要访问数据库
    // 所以要通过properties配置环境变量,激活配置文件 此处是local
    // 配置文件激活后才能拿到访问数据库的相关数据
    @Autowired
    private IItemService itemService;

    @Test
    void test() {
        System.out.println("client =" + client);
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

  1. 商品的索引库结构和数据库结构存在查询, 要定义一个与索引库结构对应的实体

@Data
@ApiModel(description = "索引库实体")
public class ItemDoc{

    @ApiModelProperty("商品id")
    private String id;

    @ApiModelProperty("商品名称")
    private String name;

    @ApiModelProperty("价格(分)")
    private Integer price;

    @ApiModelProperty("商品图片")
    private String image;

    @ApiModelProperty("类目名称")
    private String category;

    @ApiModelProperty("品牌名称")
    private String brand;

    @ApiModelProperty("销量")
    private Integer sold;

    @ApiModelProperty("评论数")
    private Integer commentCount;

    @ApiModelProperty("是否是推广广告,true/false")
    private Boolean isAD;

    @ApiModelProperty("更新时间")
    private LocalDateTime updateTime;
}

  1. 新增文档的JavaAPI如下:

@SpringBootTest(properties = "spring.profiles.active=local")
public class ElasticDocumentTest {

    private RestHighLevelClient client;

    // 这个接口查询数据要访问数据库
    // 所以要通过properties配置环境变量,激活配置文件 此处是local
    // 配置文件激活后才能拿到访问数据库的相关数据
    @Autowired
    private IItemService itemService;

    @Test
    void test() {
        System.out.println("client =" + client);
    }

    @Test
    void testAddDoc() throws IOException {
        //0 准备文档数据
        //根据id查询数据库数据
        Item item = itemService.getById(317578);
        //数据库的商品数据转为搜索库的文档数据
        ItemDoc itemDoc = BeanUtil.copyProperties(item, ItemDoc.class);

        //1 准备Request
        IndexRequest request = new IndexRequest("items").id(itemDoc.getId());
        //2 准备请求参数
        request.source(JSONUtil.toJsonStr(itemDoc), XContentType.JSON);
        //3 发送请求
        client.index(request, RequestOptions.DEFAULT);
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

  1. 使用jdk17, 需要增加一个测试启动项的vm配置, 不然会因为高版本造成 seata 报错

  1. 验证文档是否添加成功

2. 查询文档

查询文档包含查询和解析响应结果两部分。对应的IavaAPI如下


public class ElasticDocumentTest {

    private RestHighLevelClient client;

    @Test
    void test() {
        System.out.println("client =" + client);
    }

    @Test
    void testGetDoc() throws IOException {
        //1 准备Request
        GetRequest request = new GetRequest("items", "317578");
        //2 发送请求
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        //3 解析结果
        String json = response.getSourceAsString();
        ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
        System.out.println("doc =" + doc);
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

3. 删除文档

删除文档的JavaAPI如下:

public class ElasticDocumentTest {

    private RestHighLevelClient client;


    @Test
    void test() {
        System.out.println("client =" + client);
    }

    @Test
    void testDelDoc() throws IOException {
        //1 准备Request
        DeleteRequest request = new DeleteRequest("items", "317578");
        //2 发送请求
        client.delete(request, RequestOptions.DEFAULT);
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

4. 修改文档

修改文档数据有两种方式:

方式一: 全量更新。再次写入id一样的文档,就会删除旧文档,添加新文档。与新增的JavaAPI一致。

方式二: 局部更新。只更新指定部分字段,

public class ElasticDocumentTest {

    private RestHighLevelClient client;

    @Test
    void test() {
        System.out.println("client =" + client);
    }


    @Test
    void testUpdateDoc() throws IOException {
        //1 准备Request
        UpdateRequest request = new UpdateRequest("items", "317578");
        //2 准备请求参数
        request.doc(
                "price", 100
        );
        //3 发送请求
        client.update(request, RequestOptions.DEFAULT);
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

5. 批量操作

批处理代码流程与之前类似,只不过构建请求会用到一个名为BulkRequest来封装普通的CRUD请求:

批处理的API示例:

public class ElasticDocumentTest {

    private RestHighLevelClient client;

    @Test
    void test() {
        System.out.println("client =" + client);
    }

    @Test
    void testBulkDoc() throws IOException {
        //1 准备Request
        BulkRequest request = new BulkRequest();
        //2 准备请求参数
        request.add(new IndexRequest("items").id("1").source("json", XContentType.JSON));
        request.add(new DeleteRequest("items").id("1"));
        //3 发送请求
        client.bulk(request, RequestOptions.DEFAULT);
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}

把数据库的数据批量添加到索引库

@SpringBootTest(properties = "spring.profiles.active=local")
public class ElasticDocumentTest {

    private RestHighLevelClient client;

    // 这个接口查询数据要访问数据库
    // 所以要通过properties配置环境变量,激活配置文件 此处是local
    // 配置文件激活后才能拿到访问数据库的相关数据
    @Autowired
    private IItemService itemService;

    @Test
    void test() {
        System.out.println("client =" + client);
    }


    @Test
    void testBulkDoc() throws IOException {
        int pageNo = 1, pageSize = 500;
        while (true) {
            //1 准备文档数据
            Page<Item> page = itemService.lambdaQuery().eq(Item::getStatus, 1).page(new Page(pageNo, pageSize));
            List<Item> records = page.getRecords();
            if (records.isEmpty() || records == null) {
                return;
            }

            //2 准备Request
            BulkRequest request = new BulkRequest();
            //3 准备请求参数
            for (Item item : records) {
                request.add(new IndexRequest("items")
                        .id(item.getId().toString())
                        .source(JSONUtil.toJsonStr(BeanUtil.copyProperties(item, ItemDoc.class)), XContentType.JSON));
            }
            //4 发送请求
            client.bulk(request, RequestOptions.DEFAULT);

            //5 翻页
            pageNo++;
        }
    }


    @BeforeEach
    void setup() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.1.97:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }
}


http://www.kler.cn/a/454535.html

相关文章:

  • LabVIEW应用在工业车间
  • Goland 安装与使用
  • ArcGIS土地利用数据制备、分析及基于FLUS模型土地利用预测(数据采集、处理、分析、制图)
  • MacOS下TestHubo安装配置指南
  • 对gPTP上PTP安全控制的评估
  • Spring Boot 中 Map 的最佳实践
  • 【从零开始入门unity游戏开发之——C#篇33】C#委托(`Delegate`)和事件(`event` )、事件与委托的区别、Invoke()的解释
  • Spring Boot的开发工具(DevTools)模块中的热更新特性导致的问题
  • Vue3 Suspense:处理异步渲染过程
  • 力扣-数据结构-4【算法学习day.75】
  • EleutherAI/pythia-70m
  • 联通移动大内网如何使用plex流媒体服务器
  • 讲一个自己写的 excel 转 html 的 java 工具
  • 三只脚的电感是什么东西?
  • Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉
  • 更改 pnpm 的全局存储位置
  • User Script Sandboxing作用 及 在iOS项目中获取GitCommitHash
  • MacOS安装Xcode(非App Store)
  • 2-197 基于matlab的生物地理学优化算法(BBO)在无人机三维航迹规划中的应用
  • Nature+Science=ONNs(光学神经网络)
  • html文件通过script标签引入外部js文件,但没正确加载的原因
  • 1_H5视频播放器-1 -- [前端开发之道:通过实例掌握编程思维]
  • Centos7配置webrtc-streamer环境
  • 识别后端返回的字符串中携带的空格 以及换行 要在前端展示 v-html
  • Python初识
  • MySQL从入门到入土---MySQL表的约束 (内含实践)---详细版