【ElasticSearch】JavaRestClient实现文档查询、排序、分页、高亮

男娘i 2023-10-13 13:13 152阅读 0赞

文章目录

  • 1、入门案例
  • 2、全文检索
  • 3、精确查询
  • 4、复合查询-boolean query
  • 5、排序和分页
  • 6、高亮

1、入门案例

先初始化JavaRestClient对象:

  1. @SpringBootTest
  2. public class HotelSearchTest {
  3. private RestHighLevelClient client;
  4. @Test
  5. void testInit() {
  6. System.out.println(client);
  7. }
  8. @BeforeEach
  9. void setUp() {
  10. this.client = new RestHighLevelClient(RestClient.builder(
  11. HttpHost.create("http://10.4.130.220:9200")
  12. ));
  13. }
  14. @AfterEach
  15. void tearDown() throws IOException {
  16. this.client.close();
  17. }
  18. }
  19. match_all来演示基本的API使用:

代码和DSL对应上就是:

在这里插入图片描述

运行结果:

在这里插入图片描述

然后是对结果的解析,对照响应结果:

在这里插入图片描述

示例代码:

  1. @Test
  2. void testMatchAll() throws IOException {
  3. SearchRequest request = new SearchRequest("hotel");
  4. request.source()
  5. .query(QueryBuilders.matchAllQuery());
  6. SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  7. SearchHits searchHits = response.getHits();
  8. long total = searchHits.getTotalHits().value;
  9. SearchHit[] hits = searchHits.getHits();
  10. for (SearchHit hit : hits) {
  11. String json = hit.getSourceAsString();
  12. HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
  13. System.out.println(hotelDoc);
  14. }
  15. }

运行结果:

在这里插入图片描述

总结:

  • 构建DSL是通过HighLevelRestClient中的resource()方法来实现的,这里包含了查询、排序、分页、高亮等操作
    在这里插入图片描述
  • 构建查询条件的核心部分,即查询类型,是用一个名为QueryBuilders的工具类实现的,它包含了各种查询方法
    在这里插入图片描述
  • 查询的基本步骤总结:
    在这里插入图片描述

2、全文检索

和match_all一样,不同的是在QueryBuildes工具类中选的方法不同:

  1. // 单字段查询
  2. QueryBuilders.matchQuery("all", "如家");
  3. // 多字段查询
  4. QueryBuilders.multiMatchQuery("如家", "name", "business");

对比下DSL语句:
在这里插入图片描述

  1. @Test
  2. void testMatch() throws IOException {
  3. SearchRequest request = new SearchRequest("hotel");
  4. request.source()
  5. .query(QueryBuilders.matchQuery("all", "如家"));
  6. SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  7. handleResponse(response);//对响应的处理代码相同,做抽取
  8. }
  9. private void handleResponse(SearchResponse response) {
  10. SearchHits searchHits = response.getHits();
  11. long total = searchHits.getTotalHits().value;
  12. SearchHit[] hits = searchHits.getHits();
  13. for (SearchHit hit : hits) {
  14. String json = hit.getSourceAsString();
  15. HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
  16. System.out.println(hotelDoc);
  17. }
  18. }

对响应的处理代码相同,这里做个抽取,Ctrl + Alt +M(没用的话Ctrl + Alt + Shift + T,再选Extract Method), 再不行就Settings -> Keymap来打开快捷键设置对话框

在这里插入图片描述

运行:

在这里插入图片描述

3、精确查询

精确查询常见的有term查询和range查询,同样利用QueryBuilders实现

  1. // 词条查询
  2. QueryBuilders.termQuery("city", "杭州");
  3. // 范围查询
  4. QueryBuilders.rangeQuery("price").gte(100).lte(150);

与DSL对比:

在这里插入图片描述

  1. @Test
  2. void testRangeQuery() throws IOException {
  3. SearchRequest request = new SearchRequest("hotel");
  4. request.source()
  5. .query(QueryBuilders.rangeQuery("price").gte(100).lte(300));
  6. SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  7. handleResponse(response);
  8. }

运行:

在这里插入图片描述

4、复合查询-boolean query

  1. // 创建布尔查询
  2. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  3. // 添加must条件
  4. boolQuery.must(QueryBuilders.termQuery("city", "杭州"));
  5. // 添加filter条件
  6. boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

和DSL的对比:

在这里插入图片描述

  1. @Test
  2. void testBooleanQuery() throws IOException {
  3. //准备Request
  4. SearchRequest request = new SearchRequest("hotel");
  5. //准备DSL
  6. //2.1 准备BooleanQuery
  7. BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();
  8. //2.2 添加term,用must
  9. booleanQuery.must(QueryBuilders.termQuery("city", "上海"));
  10. //2.3 添加range,用filter
  11. booleanQuery.filter(QueryBuilders.rangeQuery("price").gt(100)); //大于300,lt是小于,less than
  12. //2.4 测试下mustNot
  13. booleanQuery.mustNot(QueryBuilders.rangeQuery("price").gte(500)); //大于等于500取反,小于500
  14. //2.5 玩玩should,或
  15. booleanQuery.should(QueryBuilders.termQuery("name", "北京宝辰饭店"));
  16. request.source().query(booleanQuery);
  17. //3.发送请求
  18. SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  19. //4.调用上面抽取的方法解析响应
  20. handleResponse(response);
  21. }

运行:

在这里插入图片描述

5、排序和分页

  1. // 查询
  2. request.source().query(QueryBuilders.matchAllQuery());
  3. // 分页
  4. request.source().from(0).size(5);
  5. // 价格排序
  6. request.source().sort("price", SortOrder.ASC);

和DSL的对应关系:

在这里插入图片描述

  1. //pageNum和pageSize从前端Dto获取,
  2. //则起点为(pageNum-1)*pageSize
  3. request.source().from((pageNum - 1)*pageSize).size(pageSize);
  4. @Test
  5. void testPage() throws IOException {
  6. int pageNum = 2;
  7. int pageSize = 3;
  8. SearchRequest request = new SearchRequest("hotel");
  9. request.source()
  10. .query(QueryBuilders.matchQuery("name", "如家"));
  11. request.source().from((pageNum - 1) * pageSize).size(pageSize);
  12. request.source().sort("price", SortOrder.ASC);
  13. SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  14. handleResponse(response);
  15. }

运行:

在这里插入图片描述

6、高亮

高亮API包括请求DSL构建和结果解析两部分,DSL构建为:

  1. request.source().highlighter(new HighlightBuilder()
  2. .field("name")
  3. // 是否需要与查询字段匹配
  4. .requireFieldMatch(false)
  5. );

在这里插入图片描述
不用默认标签的话也可以,继续链式编程,后面调postTags()等方法即可。

  1. @Test
  2. void testHighLighter() throws IOException {
  3. SearchRequest request = new SearchRequest("hotel");
  4. request.source()
  5. .query(QueryBuilders.matchQuery("all","如家"))
  6. .highlighter(new HighlightBuilder().field("name")
  7. .requireFieldMatch(false)
  8. .preTags("<strong>")
  9. .postTags("</strong")
  10. );
  11. SearchResponse response = client.search(request,RequestOptions.DEFAULT);
  12. handleResponse(response);
  13. }

发现结果并未高亮,因为上面抽取的handleResponse方法是对_source下处理的,这里的数据是原数据,本就不会被修改,因此要继续拿highlight下的数据,即解析高亮结果

在这里插入图片描述

  1. @Test
  2. void testHighLighter() throws IOException {
  3. SearchRequest request = new SearchRequest("hotel");
  4. request.source()
  5. .query(QueryBuilders.matchQuery("all","如家"))
  6. .highlighter(new HighlightBuilder().field("name")
  7. .requireFieldMatch(false)
  8. .preTags("<strong>")
  9. .postTags("</strong")
  10. );
  11. SearchResponse response = client.search(request,RequestOptions.DEFAULT);
  12. SearchHits searchHits = response.getHits();
  13. SearchHit[] hits = searchHits.getHits();
  14. for(SearchHit hit : hits){
  15. String hotelDocString = hit.getSourceAsString();
  16. HotelDoc hotelDoc = JSON.parseObject(hotelDocString,HotelDoc.class);
  17. Map<String, HighlightField> highlightFieldMap = hit.getHighlightFields();
  18. if(! CollectionUtils.isEmpty(highlightFieldMap)){
  19. HighlightField highlightField = highlightFieldMap.get("name");
  20. if(highlightField != null){
  21. String name = highlightField.getFragments()[0].string();
  22. hotelDoc.setName(name);
  23. System.out.println(hotelDoc);
  24. }
  25. }
  26. }
  27. }

运行:

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,152人围观)

还没有评论,来说两句吧...

相关阅读