SpringBoot整合Elasticsearch7基于RestHighLevelClient工具类(分页,高亮)

约定不等于承诺〃 2021-09-01 07:00 913阅读 0赞

1.主要依赖

  1. <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
  2. <dependency>
  3. <groupId>cn.hutool</groupId>
  4. <artifactId>hutool-all</artifactId>
  5. <version>5.3.10</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>commons-lang</groupId>
  9. <artifactId>commons-lang</artifactId>
  10. <version>2.6</version>
  11. </dependency>
  12. <!--返回json字符窜的支持 -->
  13. <dependency>
  14. <groupId>com.alibaba</groupId>
  15. <artifactId>fastjson</artifactId>
  16. <version>1.2.58</version>
  17. </dependency>
  18. <!--elasticsearch-->
  19. <dependency>
  20. <groupId>org.springframework.boot</groupId>
  21. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  22. </dependency>

简单配置

  1. @Configuration
  2. public class ElasticsearchConfig {
  3. @Bean
  4. public RestHighLevelClient restHighLevelClient(){
  5. RestHighLevelClient client=new RestHighLevelClient(
  6. RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));
  7. return client;
  8. }
  9. }

2.查询条件QueryBuilder的构建方法举例

在使用聚合查询之前我们有必要先来了解下创建查询条件QueryBuilder的几种常用方法

2.1精确查询(必须完全匹配上)

  1. 单个匹配termQuery
  2. //不分词查询 参数1: 字段名,参数2:字段查询值,因为不分词,所以汉字只能查询一个字,英语是一个单词.
  3. QueryBuilder queryBuilder=QueryBuilders.termQuery("fieldName", "fieldlValue");
  4. //分词查询,采用默认的分词器
  5. QueryBuilder queryBuilder2 = QueryBuilders.matchQuery("fieldName", "fieldlValue");
  6. 多个匹配
  7. //不分词查询,参数1: 字段名,参数2:多个字段查询值,因为不分词,所以汉字只能查询一个字,英语是一个单词.
  8. QueryBuilder queryBuilder=QueryBuilders.termsQuery("fieldName", "fieldlValue1","fieldlValue2...");
  9. //分词查询,采用默认的分词器
  10. QueryBuilder queryBuilder= QueryBuilders.multiMatchQuery("fieldlValue", "fieldName1", "fieldName2", "fieldName3");
  11. //匹配所有文件,相当于就没有设置查询条件
  12. QueryBuilder queryBuilder=QueryBuilders.matchAllQuery();

2.2模糊查询(只要包含即可)

  1. //模糊查询常见的5个方法如下
  2. //1.常用的字符串查询
  3. QueryBuilders.queryStringQuery("fieldValue").field("fieldName");//左右模糊
  4. //2.常用的用于推荐相似内容的查询
  5. QueryBuilders.moreLikeThisQuery(new String[] { "fieldName"}).addLikeText("pipeidhua");//如果不指定filedName,则默认全部,常用在相似内容的推荐上
  6. //3.前缀查询 如果字段没分词,就匹配整个字段前缀
  7. QueryBuilders.prefixQuery("fieldName","fieldValue");
  8. //4.fuzzy query:分词模糊查询,通过增加fuzziness模糊属性来查询,如能够匹配hotelName为tel前或后加一个字母的文档,fuzziness 的含义是检索的term 前后增加或减少n个单词的匹配查询
  9. QueryBuilders.fuzzyQuery("hotelName", "tel").fuzziness(Fuzziness.ONE);
  10. //5.wildcard query:通配符查询,支持* 任意字符串;?任意一个字符
  11. QueryBuilders.wildcardQuery("fieldName","ctr*");//前面是fieldname,后面是带匹配字符的字符串
  12. QueryBuilders.wildcardQuery("fieldName","c?r?");

2.3范围查询

  1. //闭区间查询
  2. QueryBuilder queryBuilder0 = QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2");
  3. //开区间查询
  4. QueryBuilder queryBuilder1 = QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2").includeUpper(false).includeLower(false);//默认是true,也就是包含
  5. //大于
  6. QueryBuilder queryBuilder2 = QueryBuilders.rangeQuery("fieldName").gt("fieldValue");
  7. //大于等于
  8. QueryBuilder queryBuilder3 = QueryBuilders.rangeQuery("fieldName").gte("fieldValue");
  9. //小于
  10. QueryBuilder queryBuilder4 = QueryBuilders.rangeQuery("fieldName").lt("fieldValue");
  11. //小于等于
  12. QueryBuilder queryBuilder5 = QueryBuilders.rangeQuery("fieldName").lte("fieldValue");

2.4组合查询/多条件查询/布尔查询

  1. QueryBuilders.boolQuery()
  2. QueryBuilders.boolQuery().must();//文档必须完全匹配条件,相当于and
  3. QueryBuilders.boolQuery().mustNot();//文档必须不匹配条件,相当于not
  4. QueryBuilders.boolQuery().should();//至少满足一个条件,这个文档就符合should,相当于or

3.工具类

  1. /** * @Author: dxf * @Description: Elasticsearch工具类 * @Date: Created in 2020-08-22 17:49 * @Modified By: */
  2. @Component
  3. @Slf4j
  4. public class ElasticsearchUtil {
  5. //最好不要自定义id 会影响插入速度。
  6. @Autowired
  7. @Qualifier("restHighLevelClient")
  8. private RestHighLevelClient restHighLevelClient;
  9. /** * 创建索引 * @param index * @return */
  10. public boolean createIndex(String index) throws IOException {
  11. if(isIndexExist(index)){
  12. log.error("Index is exits!");
  13. return false;
  14. }
  15. //1.创建索引请求
  16. CreateIndexRequest request = new CreateIndexRequest(index);
  17. //2.执行客户端请求
  18. org.elasticsearch.client.indices.CreateIndexResponse response = restHighLevelClient.indices()
  19. .create(request, RequestOptions.DEFAULT);
  20. return response.isAcknowledged();
  21. }
  22. /** * 判断索引是否存在 * @param index * @return */
  23. public boolean isIndexExist(String index) throws IOException {
  24. GetIndexRequest request = new GetIndexRequest(index);
  25. boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
  26. return exists;
  27. }
  28. /** * 删除索引 * @param index * @return */
  29. public boolean deleteIndex(String index) throws IOException {
  30. if(!isIndexExist(index)) {
  31. log.error("Index is not exits!");
  32. return false;
  33. }
  34. DeleteIndexRequest request = new DeleteIndexRequest(index);
  35. AcknowledgedResponse delete = restHighLevelClient.indices()
  36. .delete(request, RequestOptions.DEFAULT);
  37. return delete.isAcknowledged();
  38. }
  39. /** * 数据添加,自定义id * @param object 要增加的数据 * @param index 索引,类似数据库 * @param id 数据ID,为null时es随机生成 * @return */
  40. public String addData(Object object, String index, String id) throws IOException {
  41. //创建请求
  42. IndexRequest request = new IndexRequest(index);
  43. //规则 put /test_index/_doc/1
  44. request.id(id);
  45. request.timeout(TimeValue.timeValueSeconds(1));
  46. //将数据放入请求 json
  47. IndexRequest source = request.source(JSON.toJSONString(object), XContentType.JSON);
  48. //客户端发送请求
  49. IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
  50. return response.getId();
  51. }
  52. /** * 数据添加 随机id * @param object 要增加的数据 * @param index 索引,类似数据库 * @return */
  53. public String addData(Object object, String index) throws IOException {
  54. return addData(object, index, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
  55. }
  56. /** * 通过ID删除数据 * @param index 索引,类似数据库 * @param id 数据ID * @return */
  57. public void deleteDataById(String index,String id) throws IOException {
  58. DeleteRequest request = new DeleteRequest(index, id);
  59. restHighLevelClient.delete(request, RequestOptions.DEFAULT);
  60. }
  61. /** * 通过ID 更新数据 * @param object 要更新数据 * @param index 索引,类似数据库 * @param id 数据ID * @return */
  62. public void updateDataById(Object object, String index, String id) throws IOException {
  63. UpdateRequest update = new UpdateRequest(index, id);
  64. update.timeout("1s");
  65. update.doc(JSON.toJSONString(object), XContentType.JSON);
  66. restHighLevelClient.update(update, RequestOptions.DEFAULT);
  67. }
  68. /** * 通过ID获取数据 * @param index 索引,类似数据库 * @param id 数据ID * @param fields 需要显示的字段,逗号分隔(缺省为全部字段) * @return */
  69. public Map<String,Object> searchDataById(String index, String id, String fields) throws IOException {
  70. GetRequest request = new GetRequest(index, id);
  71. if (StringUtils.isNotEmpty(fields)){
  72. //只查询特定字段。如果需要查询所有字段则不设置该项。
  73. request.fetchSourceContext(new FetchSourceContext(true,fields.split(","), Strings.EMPTY_ARRAY));
  74. }
  75. GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
  76. return response.getSource();
  77. }
  78. /** * 通过ID判断文档是否存在 * @param index 索引,类似数据库 * @param id 数据ID * @return */
  79. public boolean existsById(String index,String id) throws IOException {
  80. GetRequest request = new GetRequest(index, id);
  81. //不获取返回的_source的上下文
  82. request.fetchSourceContext(new FetchSourceContext(false));
  83. request.storedFields("_none_");
  84. return restHighLevelClient.exists(request, RequestOptions.DEFAULT);
  85. }
  86. /** * 批量插入false成功 * @param index 索引,类似数据库 * @param objects 数据 * @return */
  87. public boolean bulkPost(String index, List<?> objects) {
  88. BulkRequest bulkRequest = new BulkRequest();
  89. BulkResponse response=null;
  90. //最大数量不得超过20万
  91. for (Object object: objects) {
  92. IndexRequest request = new IndexRequest(index);
  93. request.source(JSON.toJSONString(object), XContentType.JSON);
  94. bulkRequest.add(request);
  95. }
  96. try {
  97. response=restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
  98. } catch (IOException e) {
  99. e.printStackTrace();
  100. }
  101. return response.hasFailures();
  102. }
  103. /** * 根据经纬度查询范围查找location 经纬度字段,distance 距离中心范围KM,lat lon 圆心经纬度 * @param index * @param longitude * @param latitude * @param distance * @return */
  104. public SearchResponse geoDistanceQuery(String index,Float longitude, Float latitude,String distance) throws IOException {
  105. if(longitude == null || latitude == null){
  106. return null;
  107. }
  108. //拼接条件
  109. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  110. // QueryBuilder isdeleteBuilder = QueryBuilders.termQuery("isdelete", false);
  111. // 以某点为中心,搜索指定范围
  112. GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder("location");
  113. distanceQueryBuilder.point(latitude, longitude);
  114. //查询单位:km
  115. distanceQueryBuilder.distance(distance, DistanceUnit.KILOMETERS);
  116. boolQueryBuilder.filter(distanceQueryBuilder);
  117. // boolQueryBuilder.must(isdeleteBuilder);
  118. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  119. searchSourceBuilder.query(boolQueryBuilder);
  120. SearchRequest searchRequest = new SearchRequest(index);
  121. searchRequest.source(searchSourceBuilder);
  122. SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
  123. return searchResponse;
  124. }
  125. /** * 获取低水平客户端 * @return */
  126. public RestClient getLowLevelClient() {
  127. return restHighLevelClient.getLowLevelClient();
  128. }
  129. /** * 高亮结果集 特殊处理 * map转对象 JSONObject.parseObject(JSONObject.toJSONString(map), Content.class) * @param searchResponse * @param highlightField */
  130. private List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
  131. //解析结果
  132. ArrayList<Map<String,Object>> list = new ArrayList<>();
  133. for (SearchHit hit : searchResponse.getHits().getHits()) {
  134. Map<String, HighlightField> high = hit.getHighlightFields();
  135. HighlightField title = high.get(highlightField);
  136. Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
  137. //解析高亮字段,将原来的字段换为高亮字段
  138. if (title!=null){
  139. Text[] texts = title.fragments();
  140. String nTitle="";
  141. for (Text text : texts) {
  142. nTitle+=text;
  143. }
  144. //替换
  145. sourceAsMap.put(highlightField,nTitle);
  146. }
  147. list.add(sourceAsMap);
  148. }
  149. return list;
  150. }
  151. /** * 查询并分页 * @param index 索引名称 * @param query 查询条件 * @param size 文档大小限制 * @param fields 需要显示的字段,逗号分隔(缺省为全部字段) * @param sortField 排序字段 * @param highlightField 高亮字段 * @return */
  152. public List<Map<String, Object>> searchListData(String index,
  153. SearchSourceBuilder query,
  154. Integer size,
  155. Integer from,
  156. String fields,
  157. String sortField,
  158. String highlightField) throws IOException {
  159. SearchRequest request = new SearchRequest(index);
  160. SearchSourceBuilder builder = query;
  161. if (StringUtils.isNotEmpty(fields)){
  162. //只查询特定字段。如果需要查询所有字段则不设置该项。
  163. builder.fetchSource(new FetchSourceContext(true,fields.split(","),Strings.EMPTY_ARRAY));
  164. }
  165. from = from <= 0 ? 0 : from*size;
  166. //设置确定结果要从哪个索引开始搜索的from选项,默认为0
  167. builder.from(from);
  168. builder.size(size);
  169. if (StringUtils.isNotEmpty(sortField)){
  170. //排序字段,注意如果proposal_no是text类型会默认带有keyword性质,需要拼接.keyword
  171. builder.sort(sortField+".keyword", SortOrder.ASC);
  172. }
  173. //高亮
  174. HighlightBuilder highlight = new HighlightBuilder();
  175. highlight.field(highlightField);
  176. //关闭多个高亮
  177. highlight.requireFieldMatch(false);
  178. highlight.preTags("<span style='color:red'>");
  179. highlight.postTags("</span>");
  180. builder.highlighter(highlight);
  181. //不返回源数据。只有条数之类的数据。
  182. // builder.fetchSource(false);
  183. request.source(builder);
  184. SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  185. log.error("=="+response.getHits().getTotalHits());
  186. if (response.status().getStatus() == 200) {
  187. // 解析对象
  188. return setSearchResponse(response, highlightField);
  189. }
  190. return null;
  191. }
  192. }

发表评论

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

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

相关阅读