上一节讲述了 [SpringBoot 实现 elasticsearch 索引操作], 这一章节讲述 SpringBoot 实现 elasticsearch 查询操作。
1. 环境准备
案例用到的索引库结构
PUT /hotel { "mappings": { "properties": { "id": { "type": "keyword" }, "name":{ "type": "text", "analyzer": "ik_max_word", "copy_to": "all" }, "address":{ "type": "keyword", "index": false }, "price":{ "type": "integer" }, "score":{ "type": "integer" }, "brand":{ "type": "keyword", "copy_to": "all" }, "city":{ "type": "keyword", "copy_to": "all" }, "starName":{ "type": "keyword" }, "business":{ "type": "keyword" }, "location":{ "type": "geo_point" }, "pic":{ "type": "keyword", "index": false }, "all":{ "type": "text", "analyzer": "ik_max_word" } } } }
2. 查询全部
@GetMapping("/searchAll") public List<HotelDoc> searchAll() throws Exception { //1.创建请求语义对象 SearchRequest searchRequest = new SearchRequest("索引名称"); // QueryBuilders: 构建查询类型 searchRequest.source().query(QueryBuilders.matchAllQuery()); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return handleResponse(searchResponse); }
3. 根据 name 查询 match 分词查询
@GetMapping("/searchByName/{name}") public List<HotelDoc> searchByName(@PathVariable("name") String name) throws Exception { //1.创建请求语义对象 SearchRequest searchRequest = new SearchRequest("索引名称"); // QueryBuilders: 构建查询类型 searchRequest.source().query(QueryBuilders.matchQuery("name", name)); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return handleResponse(searchResponse); }
4. 根据 name 和 品牌查询 multiMatch 分词查询
@GetMapping("/searchByNameAndBrand/{name}") public List<HotelDoc> searchByNameAndBrand(@PathVariable("name") String name) throws Exception { //1.创建请求语义对象 SearchRequest searchRequest = new SearchRequest("索引名称"); // QueryBuilders: 构建查询类型 searchRequest.source().query(QueryBuilders.multiMatchQuery(name,"name","brand")); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return handleResponse(searchResponse); }
5. 根据 brand 查询 match 分词查询
@GetMapping("/searchByBrand/{name}") public List<HotelDoc> searchByBrand(@PathVariable("name") String name) throws Exception { //1.创建请求语义对象 SearchRequest searchRequest = new SearchRequest("索引名称"); // QueryBuilders: 构建查询类型 searchRequest.source().query(QueryBuilders.matchQuery("brand", name)); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return handleResponse(searchResponse); }
6. 按照价格 范围查询
@GetMapping("/searchByPrice/{low}/{high}") public List<HotelDoc> searchByPrice(@PathVariable("low") String low, @PathVariable("high") String high) throws Exception { //1.创建请求语义对象 SearchRequest searchRequest = new SearchRequest("索引名称"); // QueryBuilders: 构建查询类型 searchRequest.source().query(QueryBuilders.rangeQuery("price").gte(low).lte(high)); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return handleResponse(searchResponse); }
7. 精确查询
@GetMapping("/termQueryCity/{city}") public List<HotelDoc> termQueryCity(@PathVariable("city") String city) throws Exception { //1.创建请求语义对象 SearchRequest searchRequest = new SearchRequest("索引名称"); // QueryBuilders: 构建查询类型 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //searchSourceBuilder.query(QueryBuilders.termQuery("city", city)); 这行有点小问题 // https://zhuanlan.zhihu.com/p/270426807 参考 searchSourceBuilder.query(QueryBuilders.termQuery("city.keyword", city)); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return handleResponse(searchResponse); }
8. boolQuery
@GetMapping("/testBool") public List<HotelDoc> testBool() throws Exception { // 1.准备Request SearchRequest request = new SearchRequest("索引名称"); // 2.准备DSL // 2.1.准备BooleanQuery BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); // 2.2.添加term boolQuery.must(QueryBuilders.termQuery("city.keyword", "杭州")); // 2.3.添加range boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250)); request.source().query(boolQuery); // 3.发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4.解析响应 return handleResponse(response); }
9. 分页
@GetMapping("/testPageAndSort/{currentPage}/{pageSize}") public List<HotelDoc> testPageAndSort(@PathVariable("currentPage") Integer currentPage, @PathVariable("pageSize") Integer pageSize) throws Exception { // 页码,每页大小 // 1.准备Request SearchRequest request = new SearchRequest("索引名称"); // 2.准备DSL // 2.1.query request.source().query(QueryBuilders.matchAllQuery()); // 2.2.排序 sort request.source().sort("price", SortOrder.ASC); // 2.3.分页 from、size request.source().from((currentPage - 1) * pageSize).size(pageSize); // 3.发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4.解析响应 return handleResponse(response); }
10. 高亮查询
@GetMapping("/testHighlight/{name}") void testHighlight(@PathVariable("name") String name) throws Exception { // 1.准备Request SearchRequest request = new SearchRequest("索引名称"); // 2.准备DSL // 2.1.query request.source().query(QueryBuilders.matchQuery("name", name)); // 2.2.高亮 request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false)); // 3.发送请求 SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4.解析响应 handleResponse2(response); }
11. 公共解析
private List<HotelDoc> handleResponse(SearchResponse response) throws Exception { // 获取命中的所有内容 SearchHits searchHits = response.getHits(); // 获取命中的总条数 long count = searchHits.getTotalHits().value; System.out.println("命中的条数为: "+ count); // 获取命中的文档对象数组 SearchHit[] hits = searchHits.getHits(); List<HotelDoc> docList = new ArrayList<>(); for (SearchHit hit : hits) { // 解析每一个hit对象得到对应的文档数据 String json = hit.getSourceAsString(); // HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); docList.add(JSON.parseObject(json, HotelDoc.class)); } //destroy(); return docList; } private void handleResponse2(SearchResponse response) { // 4.解析响应 SearchHits searchHits = response.getHits(); // 4.1.获取总条数 long total = searchHits.getTotalHits().value; System.out.println("共搜索到" + total + "条数据"); // 4.2.文档数组 SearchHit[] hits = searchHits.getHits(); // 4.3.遍历 for (SearchHit hit : hits) { // 获取文档source String json = hit.getSourceAsString(); // 反序列化 HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class); // 获取高亮结果 Map<String, HighlightField> highlightFields = hit.getHighlightFields(); if ( !CollectionUtils.isEmpty(highlightFields) ) { // 根据字段名获取高亮结果 HighlightField highlightField = highlightFields.get("name"); if (highlightField != null) { // 获取高亮值 String name = highlightField.getFragments()[0].string(); // 覆盖非高亮结果 hotelDoc.setName(name); } } System.out.println("hotelDoc = " + hotelDoc); } }