Elasticsearch客户端 您所在的位置:网站首页 elasticsearch客户端源码 Elasticsearch客户端

Elasticsearch客户端

2022-12-21 03:18| 来源: 网络整理| 查看: 265

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」

客户端介绍

在elasticsearch官网中提供了各种语言的客户端:www.elastic.co/guide/en/el…

注意点击进入后,选择版本到 6.2.4 ,因为我们之前按照的都是 6.2.4 版本:

image.png

创建Demo工程 初始化项目

image.png

pom文件

注意,这里我们直接导入了SpringBoot的启动器,方便后续讲解。不过还需要手动引入elasticsearch的High-level-Rest-Client的依赖:

11 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine junit junit 4.12 test org.springframework.boot spring-boot-starter-logging com.google.code.gson gson 2.8.5 org.apache.commons commons-lang3 3.8.1 commons-beanutils commons-beanutils 1.9.1 org.elasticsearch.client elasticsearch-rest-high-level-client 6.4.3 org.springframework.boot spring-boot-maven-plugin 复制代码 配置文件

我们在resource下创建application.yml

image.png

索引库及映射

image.png

创建索引库的同时,我们也会创建type及其映射关系,但是这些操作不建议使用java客户端完成,原因如下:

索引库和映射往往是初始化时完成,不需要频繁操作,不如提前配置好 官方提供的创建索引库及映射API非常繁琐,需要通过字符串拼接json结构:

image.png

因此,这些操作建议还是使用我们昨天学习的Rest风格API去实现。

我们接下来以这样一个商品数据为例来创建索引库:

package com.lagou.es.pojo; public class Product { private Long id; private String title; //标题 private String category;// 分类 private String brand; // 品牌 private Double price; // 价格 private String images; // 图片地址 } 复制代码

分析一下数据结构:

id:可以认为是主键,将来判断数据是否重复的标示,不分词,可以使用keyword类型 title:搜索字段,需要分词,可以用text类型 category:商品分类,这个是整体,不分词,可以使用keyword类型 brand:品牌,与分类类似,不分词,可以使用keyword类型 price:价格,这个是double类型 images:图片,用来展示的字段,不搜索,index为false,不分词,可以使用keyword类型

我们可以编写这样的映射配置:

PUT /lagou { "settings": { "number_of_shards": 3, "number_of_replicas": 1 }, "mappings": { "item": { "properties": { "id": { "type": "keyword" }, "title": { "type": "text", "analyzer": "ik_max_word" }, "category": { "type": "keyword" }, "brand": { "type": "keyword" }, "images": { "type": "keyword", "index": false }, "price": { "type": "double" } } } } } 复制代码 索引数据操作

有了索引库,我们接下来看看如何新增索引数据

操作MYSQL数据库:

获取数据库连接 完成数据的增删改查 释放资源 初始化客户端

完成任何操作都需要通过HighLevelRestClient客户端,看下如何创建。

我们先编写一个测试类:

image.png

然后再@Before的方法中编写client初始化:

public class ElasticSearchTest { private RestHighLevelClient client; // Json工具 private Gson gson = new Gson(); @Before public void init(){ // 初始化HighLevel客户端 client = new RestHighLevelClient( RestClient.builder( new HttpHost("127.0.0.1", 9201, "http"), new HttpHost("127.0.0.1", 9202, "http"), new HttpHost("127.0.0.1", 9203, "http") ) ); } @After public void close() throws IOException { // 关闭客户端 client.close(); } } 复制代码 新增文档 @Test public void testInsert() throws IOException { //1.文档数据 Product product = new Product(); product.setBrand("华为"); product.setCategory("手机"); product.setId(1L); product.setImages("http://image.huawei.com/1.jpg"); product.setPrice(5999.99); product.setTitle("华为P50就是棒"); //2.将文档数据转换为json格式 String source = gson.toJson(product); //3.创建索引请求对象 访问哪个索引库、哪个type、指定文档ID //public IndexRequest(String index, String type, String id) IndexRequest request = new IndexRequest("lagou","item",product.getId().toString()); request.source(source, XContentType.JSON); //4.发出请求 IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT); System.out.println(response); } 复制代码 查看文档

根据rest风格,查看应该是根据id进行get查询,难点是对结果的解析:

@Test public void testFindIndex() throws IOException { // 创建get请求,并指定id GetRequest request = new GetRequest("lagou", "item", "1"); // 查询,得到响应 GetResponse response = client.get(request, RequestOptions.DEFAULT); // 解析响应,应该是json String source = response.getSourceAsString(); // 转换json数据 Product item = gson.fromJson(source, Product.class); System.out.println(item); } 复制代码 修改文档

新增时,如果传递的id是已经存在的,则会完成修改操作,如果不存在,则是新增。

删除文档

根据id删除:

@Test public void testDeleteIndex() throws IOException { // 准备删除的请求,参数为id DeleteRequest request = new DeleteRequest("lagou", "item", "1"); // 发起请求 DeleteResponse response = client.delete(request, RequestOptions.DEFAULT); System.out.println("response = " + response); } 复制代码 搜索数据 查询所有match_all @Test public void testMatchAll() throws IOException { // 创建搜索对象 SearchRequest request = new SearchRequest(); // 查询构建工具 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.matchAllQuery()); request.source(sourceBuilder); // 搜索 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 解析 SearchHits hits = response.getHits(); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // 取出source数据 String json = hit.getSourceAsString(); // 反序列化 Product item = gson.fromJson(json, Item.class); System.out.println("item = " + item); } } 复制代码

注意,上面的代码中,搜索条件是通过 sourceBuilder.query(QueryBuilders.matchAllQuery())来添加的。这个 query() 方法接受的参数是: QueryBuilder 接口类型。

这个接口提供了很多实现类,分别对应我们在之前中学习的不同类型的查询,例如:term查询、match查询、range查询、boolean查询等

因此,我们如果要使用各种不同查询,其实仅仅是传递给 sourceBuilder.query() 方法的参数不同而已。而这些实现类不需要我们去 new ,官方提供了 QueryBuilders 工厂帮我们构建各种实现类

关键字搜索match

其实搜索类型的变化,仅仅是利用QueryBuilders构建的查询对象不同而已,其他代码基本一致:

// 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.matchQuery("title","手机")); 复制代码

因此,我们可以把这段代码封装,然后把查询条件作为参数传递:

private void basicQuery(SearchSourceBuilder sourceBuilder) throws IOException { // 创建搜索对象 SearchRequest request = new SearchRequest(); request.source(sourceBuilder); // 搜索 SearchResponse response = client.search(request,RequestOptions.DEFAULT); // 解析 SearchHits hits = response.getHits(); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // 取出source数据 String json = hit.getSourceAsString(); // 反序列化 Product item = gson.fromJson(json, Item.class); System.out.println("item = " + item); } } 复制代码

调用封装的方法,并传递查询条件:

@Test public void testMatchQuery() throws IOException { // 查询构建工具 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.matchQuery("title", "手机")); basicQuery(sourceBuilder); } 复制代码 范围查询range RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price"); 复制代码

与页面上一样,支持下面的范围关键字:

方法说明gt(Object from)大于gte(Object from)大于等于lt(Object from)小于lte(Object from)小于等于

示例:

@Test public void testRangeQuery() throws IOException { // 查询构建工具 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.rangeQuery("price").gt(1000).lt(4000)); basicQuery(sourceBuilder); } 复制代码 source过滤

_source:存储原始文档

默认情况下,索引库中所有数据都会返回,如果我们想只返回部分字段,可以通过source fifilter来控制。

@Test public void testSourceFilter() throws IOException { // 创建搜索对象 SearchRequest request = new SearchRequest(); // 查询构建工具 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加source过滤 sourceBuilder.fetchSource(new String[]{"id", "title", "price"}, null); basicQuery(sourceBuilder); } 复制代码 排序

依然是通过sourceBuilder来配置:

@Test public void testSortQuery() throws IOException { // 创建搜索对象 SearchRequest request = new SearchRequest(); // 查询构建工具 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加排序 sourceBuilder.sort("price", SortOrder.ASC); basicQuery(sourceBuilder); } 复制代码 分页

分页需要视图层传递两个参数给我们:

当前页:page 每页大小:size

而elasticsearch中需要的不是当前页,而是起始位置,还好有公式可以计算出:

from-->起始位置,0表示第一条

起始位置:start = (page - 1) * size 第一页:(1-1)*5 = 0 第二页:(2-1)*5 = 5

代码:

@Test public void testSortAndPageQuery() throws IOException { // 创建搜索对象 SearchRequest request = new SearchRequest(); // 查询构建工具 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 添加查询条件,通过QueryBuilders获取各种查询 sourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加排序 sourceBuilder.sort("price", SortOrder.ASC); // 添加分页 int page = 1; int size = 3; int start = (page - 1) * size; // 配置分页 sourceBuilder.from(start); sourceBuilder.size(3); basicQuery(sourceBuilder); } 复制代码


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有