Java实战场景下的ElasticSearch

文章目录


前言

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

  • Java Low Level Rest Client
  • Java High Level Rest Client

本文介绍的是Java HighLevel Rest Client客户端API;


一、环境准备

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类

中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

1)引入es的RestHighLevelClient依赖:

java 复制代码
dependency>
	<groupId>org.elasticsearch.client</groupId>
	<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

2)初始化RestHighLevelClient:

这里为了单元测试方便,我们创建一个测试类HotelIndexTest,然后将初始化的代码编写在

@BeforeEach方法中:

java 复制代码
/**
 * @author 杨树林
 * @version 1.0
 * @since 12/8/2023
 */
 @SpringBootTest
class HotelIndexTest{
    private RestHighLevelClient client;
    @BeforeEach
    void setUp(){
        this.client=new RestHighLevelClient(RestClient.builder
                (HttpHost.create("http://localhost:9200")));
    }
    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
 }

3)创建HotelConstants类,定义mapping映射的JSON字符串常量

java 复制代码
public class HotelConstants {
    public static final String MAPPING_TEMPLATE = "{\n" +
            "  \"mappings\": {\n" +
            "    \"properties\": {\n" +
            "      \"id\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"name\":{\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"address\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"price\":{\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"score\":{\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"brand\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"city\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"starName\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"business\":{\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"location\":{\n" +
            "        \"type\": \"geo_point\"\n" +
            "      },\n" +
            "      \"pic\":{\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"all\":{\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\"\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";
}

二、RsetAPI操作索引库

编写单元测试,实现一下功能:

1.创建索引库

java 复制代码
	@Test
	void creatHotelIndex() throws IOException {
	   //1、创建Requset对象
	   CreateIndexRequest request = new CreateIndexRequest("hotels");
	   //2、准备请求的参数:DEL语句
	   request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
	   //3、发起请求
	   client.indices().create(request,RequestOptions.DEFAULT);
	}

2.判断索引库是否存在

java 复制代码
	@Test
    void testExistsHotelIndex() throws IOException {
        //1、创建Requset对象
        GetIndexRequest  request = new GetIndexRequest("hotels");
        //2、发起请求
        boolean isExists = client.indices().exists(request,RequestOptions.DEFAULT);

        System.err.println(isExists ? "索引库已经存在!" : "索引库不存在!");
    }

3.删除索引库

java 复制代码
	@Test
    void delHotelIndex() throws IOException {
        //1、创建Requset对象
        DeleteIndexRequest request = new DeleteIndexRequest("hotels");
        //2、发起请求
        client.indices().delete(request,RequestOptions.DEFAULT);
    }

二、RsetAPI操作文档

1.新增文档

java 复制代码
	@Autowired
    HotelServiceImpl service;
    @Test
    void addDocument() throws IOException {
        // 1.根据id查询酒店数据
        Hotel hotel = service.getById("36934");
        // 2.转换为文档类型
        HotelDoc hotelDoc = new HotelDoc(hotel);
        // 3.将HotelDoc转json
        String json = JSON.toJSONString(hotelDoc);
        IndexRequest request = new IndexRequest("hotels").id(hotelDoc.getId().toString());
        request.source(json, XContentType.JSON);
        client.index(request, RequestOptions.DEFAULT);
    }

2.单条查询

java 复制代码
    @Test
    void getDocument() throws IOException {
        GetRequest request = new GetRequest("hotels","36934");

        GetResponse response =  client.get(request, RequestOptions.DEFAULT);

        String json = response.getSourceAsString();

        HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
        System.out.println(hotelDoc);
    }

3.删除文档

java 复制代码
    @Test
    void delDocument() throws IOException {
        DeleteRequest request  = new DeleteRequest("hotels","36934");
        client.delete(request,RequestOptions.DEFAULT);
    }

4.增量修改

api中全局修改与新增一致

java 复制代码
    @Test
    void UpdateDocument() throws IOException {
        UpdateRequest request = new UpdateRequest("hotels", "36934");
        request.doc(
                "name","XX酒店",
                "city","西安",
                "price", "200000",
                "starName", "八星级"
        );
        client.update(request, RequestOptions.DEFAULT);
    }

5.批量导入

java 复制代码
 	@Test
    void addBulkRequest() throws IOException {
        //查询所有酒店信息
        List<Hotel> hotels = service.list();
        //1.创建request
        BulkRequest request = new BulkRequest();
        for (Hotel hotel : hotels) {
            HotelDoc hotelDoc = new HotelDoc(hotel);
            request.add(new IndexRequest("hotels")
                    .id(hotelDoc.getId().toString())
                    .source(JSON.toJSONString(hotelDoc),XContentType.JSON));
        }
        client.bulk(request,RequestOptions.DEFAULT);
    }

6.自定义响应解析方法

java 复制代码
void show(SearchResponse response){
        //解析响应
        SearchHits searchHits =response.getHits();
        //获取总条数
        Long total = searchHits.getTotalHits().value;
        System.out.println("共搜到"+total+"条数据");
        //文档数组
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            System.err.println(json);
            HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
            System.out.println(hotelDoc);
        }
    }

四、常用的查询方法

1.MatchAll():查询所有

java 复制代码
	@Test
    void testMatchAll() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotels");
        //2、准备DEl,QueryBuilders构造查询条件
        request.source().query(QueryBuilders.matchAllQuery());
        //3.执行查询,返回响应结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应
        show(response);
    }

2.matchQuery():单字段查询

java 复制代码
	@Test
    void testMatch() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotels");
        // 2.准备DSL 参数1:字段  参数2:数据
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3.执行查询,返回响应结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应
        show(response);
    }

3.multiMatchQuery():多字段查询

java 复制代码
	@Test
    void testMultiMatch() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotels");
        // 2.准备DSL
        request.source().query(QueryBuilders.multiMatchQuery("如家","name","business"));
        //3.执行查询,返回响应结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应
        show(response);
    }

4.termQuery():词条精确值查询

java 复制代码
@Test
    void testTermQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotels");
        // 2.准备DSL
        request.source().query(QueryBuilders.termQuery("city","上海"));
        //3.执行查询,返回响应结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应
        show(response);
    }

5.rangeQuery():范围查询

java 复制代码
	@Test
    void testRangeQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotels");
        // 2.准备DSL
        request.source().query(QueryBuilders.rangeQuery("pirce").gte(100).lte(200));
        //3.执行查询,返回响应结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析响应
        show(response);
    }

6.bool复合查询

布尔查询是一个或多个查询子句的组合,子查询的组合方式有:
must :必须匹配每个子查询,类似"与";
should :选择性匹配子查询,类似"或";
must_not :必须不匹配,不参与算分,类似"非";
filter :必须匹配,类似"与",不参与算分一般搜索框用must,选择条件使用filter;

java 复制代码
@Test
    void testBool() throws IOException {
        SearchRequest request = new SearchRequest("hotels");
        //方式1
//        BoolQueryBuilder boolQuery = new BoolQueryBuilder();
//        boolQuery.must(QueryBuilders.termQuery("city","上海"));
//        boolQuery.filter(QueryBuilders.rangeQuery("price").gte(100).lte(200));
//        request.source().query(boolQuery);
        //方式2
        request.source().query(new BoolQueryBuilder()
                .must(QueryBuilders.termQuery("city","上海"))
                .filter(QueryBuilders.rangeQuery("price").gte(100).lte(200)));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        show(response);
    }

7.分页查询

java 复制代码
	 @Test
    void testPageAndSort() throws IOException {
        int page = 1, size = 5;
        String searchName = "如家";
        SearchRequest request = new SearchRequest("hotels");
        // 2.1.query
        if(searchName == null){
            request.source().query(QueryBuilders.matchAllQuery());
        }else{
            request.source().query(QueryBuilders.matchQuery("name", searchName));
        }
        // 2.2.分页 from、size
        request.source().from((page - 1) * size).size(size);
        //2.3.排序
        request.source().sort("price", SortOrder.DESC);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        show(response);
    }

相关推荐
Pluchon几秒前
硅基计划4.0 算法 二叉树深搜(DFS)
java·数据结构·算法·leetcode·深度优先·剪枝
9号达人27 分钟前
if-else 优化的折中思考:不是消灭分支,而是控制风险
java·后端·面试
不知道累,只知道类1 小时前
Java 在AWS上使用SDK凭证获取顺序
java·aws
咖啡Beans1 小时前
SpringBoot2.7集成Swagger3.0
java·swagger
聪明的笨猪猪1 小时前
Java JVM “垃圾回收(GC)”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
yumgpkpm1 小时前
华为鲲鹏 Aarch64 环境下多 Oracle 数据库汇聚操作指南 CMP(类 Cloudera CDP 7.3)
大数据·hive·hadoop·elasticsearch·zookeeper·big data·cloudera
Moniane2 小时前
时序数据库全面重构指南
java·后端·struts
Elastic 中国社区官方博客2 小时前
AI Agent 评估:Elastic 如何测试代理框架
大数据·人工智能·elasticsearch·搜索引擎
whm27772 小时前
Visual Basic 值传递与地址传递
java·开发语言·数据结构
没有bug.的程序员2 小时前
云原生与分布式架构的完美融合:从理论到生产实践
java·分布式·微服务·云原生·架构