Elasticsearch 8.17.1 JAVA工具类

打印 上一主题 下一主题

主题 866|帖子 866|积分 2608

 一、ElasticSearchUtils 

  1. package com.wssnail.elasticsearch.util;
  2. import co.elastic.clients.elasticsearch.ElasticsearchClient;
  3. import co.elastic.clients.elasticsearch._types.FieldValue;
  4. import co.elastic.clients.elasticsearch._types.Refresh;
  5. import co.elastic.clients.elasticsearch._types.aggregations.*;
  6. import co.elastic.clients.elasticsearch._types.query_dsl.MatchAllQuery;
  7. import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
  8. import co.elastic.clients.elasticsearch._types.query_dsl.Query;
  9. import co.elastic.clients.elasticsearch._types.query_dsl.TermsQuery;
  10. import co.elastic.clients.elasticsearch.core.*;
  11. import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
  12. import co.elastic.clients.elasticsearch.core.search.Hit;
  13. import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
  14. import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
  15. import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient;
  16. import co.elastic.clients.elasticsearch.indices.ExistsRequest;
  17. import co.elastic.clients.transport.endpoints.BooleanResponse;
  18. import com.alibaba.fastjson.JSON;
  19. import com.alibaba.fastjson.JSONObject;
  20. import com.wssnail.elasticsearch.constants.MetricConstant;
  21. import lombok.extern.slf4j.Slf4j;
  22. import java.io.IOException;
  23. import java.util.*;
  24. /**
  25. * @Author: 熟透的蜗牛
  26. * @CreateTime: 2023-01-05 16:47
  27. * @Description: TODO
  28. * @Version: 1.0
  29. */
  30. @Slf4j
  31. public class ElasticSearchUtils {
  32.     private ElasticsearchClient elasticsearchClient;
  33.     private static final Integer MAX_PAGE_SIZE = 1000;
  34.     public ElasticSearchUtils(ElasticsearchClient elasticsearchClient) {
  35.         this.elasticsearchClient = elasticsearchClient;
  36.     }
  37.     /*
  38.      * @description:创建索引
  39.      * @author:  熟透的蜗牛
  40.      * @date: 2023/1/5 16:58
  41.      * @param index
  42.      * @return: boolean
  43.      **/
  44.     public boolean createIndex(String index) {
  45.         try {
  46.             if (isIndexExist(index)) {
  47.                 log.error("Index is  exits!");
  48.                 return false;
  49.             }
  50.             //1.创建索引请求
  51.             CreateIndexResponse indexResponse = elasticsearchClient.indices().create(c -> c.index(index));
  52.             return indexResponse.acknowledged();
  53.         } catch (Exception e) {
  54.             log.info(">>>>>>>>>>>>>>>createIndex>>>id>>>>>>{}", e);
  55.         }
  56.         return false;
  57.     }
  58.     /*
  59.      * @description:判断索引是否存在
  60.      * @author:  熟透的蜗牛
  61.      * @date: 2023/1/5 16:59
  62.      * @param index
  63.      * @return: boolean
  64.      **/
  65.     public boolean isIndexExist(String index) {
  66.         try {
  67.             ElasticsearchIndicesClient indices = elasticsearchClient.indices();
  68.             BooleanResponse response = indices.exists(ExistsRequest.of(x -> x.index(index)));
  69.             return response.value();
  70.         } catch (Exception e) {
  71.             log.info(">>>>>>>>>>>>>>>isIndexExist>>>id>>>>>>{}", e);
  72.         }
  73.         return false;
  74.     }
  75.     /*
  76.      * @description:删除索引
  77.      * @author:  熟透的蜗牛
  78.      * @date: 2023/1/5 17:00
  79.      * @param null
  80.      * @return: null
  81.      **/
  82.     public boolean deleteIndex(String index) {
  83.         try {
  84.             if (!isIndexExist(index)) {
  85.                 log.error("Index is not exits!");
  86.                 return false;
  87.             }
  88.             DeleteIndexResponse response = elasticsearchClient.indices().delete(x -> x.index(index));
  89.             return response.acknowledged();
  90.         } catch (Exception e) {
  91.             log.info(">>>>>>>>>>>>>>>deleteIndex>>>id>>>>>>{}", e);
  92.         }
  93.         return false;
  94.     }
  95.     /*
  96.      * @description:更新数据,如果没有数据则新增
  97.      * @author:  熟透的蜗牛
  98.      * @date: 2023/1/5 17:01
  99.      * @param object 对象
  100.      * @param index 索引名称
  101.      * @param id 数据id
  102.      * @return: java.lang.String
  103.      **/
  104.     public String submitDocument(Object object, String index, String id) {
  105.         if (null == id) {
  106.             return addDocument(object, index);
  107.         }
  108.         if (this.existsById(index, id)) {
  109.             return this.updateDocumentByIdNoRealTime(object, index, id);
  110.         } else {
  111.             return addDocument(object, index, id);
  112.         }
  113.     }
  114.     /*
  115.      * @description:新增数据
  116.      * @author:  熟透的蜗牛
  117.      * @date: 2023/1/5 17:03
  118.      * @param object
  119.      * @param index
  120.      * @param id 数据id,为空时自动生成
  121.      * @return: java.lang.String
  122.      **/
  123.     public String addDocument(Object object, String index, String id) {
  124.         try {
  125.             if (null == id) {
  126.                 return addDocument(object, index);
  127.             }
  128.             if (this.existsById(index, id)) {
  129.                 return this.updateDocumentByIdNoRealTime(object, index, id);
  130.             }
  131.             IndexResponse indexResponse = elasticsearchClient.index(IndexRequest.of(x -> x.id(id).document(object).index(index)));
  132.             log.info("添加数据成功{}", indexResponse.result().jsonValue());
  133.             return id;
  134.         } catch (Exception e) {
  135.             log.info(">>>>>>>>>>>>>>>addDocument>>>id>>>>>>{}", e);
  136.         }
  137.         return null;
  138.     }
  139.     /*
  140.      * @description:新增数据,id用UUID生成
  141.      * @author:  熟透的蜗牛
  142.      * @date: 2023/1/5 17:05
  143.      * @param object
  144.      * @param index
  145.      * @return: java.lang.String
  146.      **/
  147.     public String addDocument(Object object, String index) {
  148.         try {
  149.             return addDocument(object, index, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
  150.         } catch (Exception e) {
  151.             log.info(">>>>>>>>>>>>>>>addDocument>>>>>>{}", e);
  152.         }
  153.         return null;
  154.     }
  155.     /*
  156.      * @description:根据id判断文档是否存在
  157.      * @author:  熟透的蜗牛
  158.      * @date: 2023/1/5 17:07
  159.      * @param index
  160.      * @param id
  161.      * @return: boolean
  162.      **/
  163.     public boolean existsById(String index, String id) {
  164.         try {
  165.             BooleanResponse response = elasticsearchClient.existsSource(ExistsSourceRequest.of(builder -> builder.index(index).id(id)));
  166.             return response.value();
  167.         } catch (Exception e) {
  168.             log.info(">>>>>>>>>>>>>>>existsById>>>>>>{}", e);
  169.         }
  170.         return false;
  171.     }
  172.     /*
  173.      * @description:通过id删除数据
  174.      * @author:  熟透的蜗牛
  175.      * @date: 2023/1/5 17:08
  176.      * @param index
  177.      * @param id
  178.      * @return: java.lang.String
  179.      **/
  180.     public String deleteDocumentById(String index, String id) {
  181.         try {
  182.             DeleteResponse delete = elasticsearchClient.delete(DeleteRequest.of(builder -> builder.id(id).index(index)));
  183.             log.info("删除数据成功 >>>>>>>>id为{}", delete.id());
  184.             return delete.id();
  185.         } catch (Exception e) {
  186.             log.info(">>>>>>>>>>>>>>>deleteDocumentById>>>>>>{}", e);
  187.         }
  188.         return null;
  189.     }
  190.     /*
  191.      * @description:通过id修改数据
  192.      * @author:  熟透的蜗牛
  193.      * @date: 2023/1/5 17:09
  194.      * @param null
  195.      * @return: null
  196.      **/
  197.     public String updateDocumentById(Object object, String index, String id) {
  198.         try {
  199.             UpdateRequest<Object, Object> updateRequest = new UpdateRequest.Builder<>().doc(object).index(index).id(id).build();
  200.             UpdateResponse<Object> updateResponse = elasticsearchClient.update(updateRequest, object.getClass());
  201.             log.info("索引为: {}, id为: {},updateResponseID:{}, 实时更新数据成功", index, id, updateResponse.id());
  202.         } catch (Exception e) {
  203.             log.info(">>>>>>>>>>>>>>>updateDocumentById>>>>>>{}", e);
  204.         }
  205.         return null;
  206.     }
  207.     /*
  208.      * @description:通过id实时更新数据
  209.      * @author:  熟透的蜗牛
  210.      * @date: 2023/1/5 17:11
  211.      * @param object
  212.      * @param index
  213.      * @param id
  214.      * @return: java.lang.String
  215.      **/
  216.     public String updateDocumentByIdNoRealTime(Object object, String index, String id) {
  217.         try {
  218.             UpdateResponse<?> updateResponse = elasticsearchClient.update(x -> x.id(id).index(index).doc(object)
  219.                     .refresh(Refresh.WaitFor).timeout(t -> t.time("1s")), object.getClass());
  220.             //执行更新请求
  221.             log.info("索引为: {}, id为: {},updateResponseID:{}, 实时更新数据成功", index, id, updateResponse.id());
  222.             return updateResponse.id();
  223.         } catch (Exception e) {
  224.             log.info(">>>>>>>>>>>>>>>updateDocumentByIdNoRealTime>>>>>>{}", e);
  225.         }
  226.         return null;
  227.     }
  228.     /**
  229.      * @param index
  230.      * @param id
  231.      * @param includeFields 指定返回字段
  232.      * @param excludeFields 指定排除的字段
  233.      * @description: 根据id查询指定数据
  234.      * @return: java.util.Map
  235.      * @author 熟透的蜗牛
  236.      * @date: 2025/1/19 17:39
  237.      */
  238.     public Map searchDocumentById(String index, String id, List<String> includeFields, List<String> excludeFields) {
  239.         try {
  240.             GetResponse<Map> response = elasticsearchClient.get(builder -> builder.index(index).id(id).sourceIncludes(includeFields).sourceExcludes(excludeFields), Map.class);
  241.             return response.source();
  242.         } catch (Exception e) {
  243.             log.info(">>>>>>>>>>>>>>>查询失败searchDocumentById>>>>>>{}", e);
  244.         }
  245.         return new HashMap();
  246.     }
  247.     /**
  248.      * @param index
  249.      * @param objects
  250.      * @description:批量插入,单词不能超20w
  251.      * @return: boolean
  252.      * @author 熟透的蜗牛
  253.      * @date: 2025/1/19 18:07
  254.      */
  255.     public boolean bulkPost(String index, List<Map> objects) {
  256.         try {
  257.             BulkRequest.Builder br = new BulkRequest.Builder();
  258.             objects.forEach(list -> {
  259.                 br.operations(op -> op
  260.                         .index(idx -> idx.index(index).document(list.get("data")).id((String) list.get("id"))));
  261.             });
  262.             BulkResponse result = elasticsearchClient.bulk(br.build());
  263.             if (result.errors()) {
  264.                 log.info(">>>>>>>>>>>>>>>批量插入有误");
  265.                 for (BulkResponseItem item : result.items()) {
  266.                     if (item.error() != null) {
  267.                         log.error(item.error().reason());
  268.                     }
  269.                 }
  270.                 return result.errors();
  271.             }
  272.             return true;
  273.         } catch (Exception e) {
  274.             log.error(">>>>>>异常信息{}", e);
  275.             return false;
  276.         }
  277.     }
  278.     /**
  279.      * @param index
  280.      * @param highlightField 需要高亮的字段
  281.      * @param start
  282.      * @param pageSize
  283.      * @param query
  284.      * @description: 高亮查询
  285.      * @return: java.util.List<java.lang.Object>
  286.      * @author 熟透的蜗牛
  287.      * @date: 2025/1/19 20:26
  288.      */
  289.     public List<Hit<Map>> searchHighLightFieldDocument(String index,
  290.                                                        String[] highlightField, Integer start, Integer pageSize, Query... query) {
  291.         List<Hit<Map>> hits = new ArrayList<>();
  292.         try {
  293.             SearchRequest.Builder searchBuilder = new SearchRequest.Builder().index(index);
  294.             for (int i = 0; i < highlightField.length; i++) {
  295.                 int finalI = i;
  296.                 searchBuilder.highlight(builder -> builder.preTags("<span style='color:red'>")
  297.                         .postTags("</span>").fields(highlightField[finalI], h -> h));
  298.             }
  299.             for (Query q : query) {
  300.                 if (q._kind().equals(Query.Kind.Bool)) {
  301.                     searchBuilder.query(bb -> bb.bool(b -> b.must(q)));
  302.                 }
  303.                 if (q._kind().equals(Query.Kind.Range)) {
  304.                     q.range();
  305.                 }
  306.                 if (q._kind().equals(Query.Kind.Term)) {
  307.                     q.term();
  308.                 }
  309.                 if (q._kind().equals(Query.Kind.MultiMatch)) {
  310.                     q.multiMatch();
  311.                 }
  312.                 searchBuilder.query(q);
  313.             }
  314.             searchBuilder.size(pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize);
  315.             searchBuilder.from((start - 1) * pageSize);
  316.             SearchResponse searchResponse = elasticsearchClient.search(searchBuilder.build(), Map.class);
  317.             log.info(">>>>>>>>>>>>>searchResponse{}", searchResponse);
  318.             if (searchResponse.hits().total().value() > 0) {
  319.                 hits = searchResponse.hits().hits();
  320.             }
  321.         } catch (IOException e) {
  322.             log.info(">>>>>>>>>>>>>>>searchListDocument>>>>>>{}", e);
  323.         }
  324.         return hits;
  325.     }
  326.     /**
  327.      * @param index
  328.      * @param field     需要查询的字段
  329.      * @param value     查询字段的值
  330.      * @param beanClass
  331.      * @param start
  332.      * @param pageSize
  333.      * @description:按条件精确查询
  334.      * @return: java.util.List<T>
  335.      * @author 熟透的蜗牛
  336.      * @date: 2025/1/21 1:11
  337.      */
  338.     public <T> List<T> termQuery(String index, String field, String value, Class<T> beanClass, Integer start, Integer pageSize) {
  339.         List<T> list = new ArrayList<>();
  340.         try {
  341.             Query query = MatchQuery.of(m -> m
  342.                     .field(field)
  343.                     .query(value)
  344.             )._toQuery();
  345.             SearchResponse<T> response = elasticsearchClient.search(s -> s
  346.                             .index(index)
  347.                             .query(q -> q
  348.                                     .bool(b -> b
  349.                                             .must(query)
  350.                                     )
  351.                             ).from((start - 1) * pageSize).size(pageSize),
  352.                     beanClass
  353.             );
  354.             this.queryEsData(beanClass, list, response);
  355.         } catch (Exception e) {
  356.             log.info(">>>>>>>>>>>>>>>termQuery>>>>>>{}", e);
  357.         }
  358.         return list;
  359.     }
  360.     /*
  361.      * @description:自定义查询
  362.      * @author:  熟透的蜗牛
  363.      * @date: 2023/1/9 15:49
  364.      * @param index
  365.      * @param beanClass
  366.      * @param query 查询条件
  367.      * @return: java.util.List<T>
  368.      **/
  369.     public <T> List<T> selfDefine(String index, Class<T> beanClass, Query query) {
  370.         List<T> list = new ArrayList<>();
  371.         try {
  372.             SearchResponse<T> response = elasticsearchClient.search(q -> q.index(index).query(query), beanClass);
  373.             this.queryEsData(beanClass, list, response);
  374.         } catch (Exception e) {
  375.             log.info(">>>>>>>>>>>>>>>termQuery>>>>>>{}", e);
  376.         }
  377.         return list;
  378.     }
  379.     /**
  380.      * @param indexName
  381.      * @param query
  382.      * @description: 查询文档数量
  383.      * @return: long
  384.      * @author 熟透的蜗牛
  385.      * @date: 2025/1/21 2:11
  386.      */
  387.     public <T> long count(String indexName, Query query) {
  388.         try {
  389.             CountResponse response = elasticsearchClient.count(q -> q.index(indexName).query(query));
  390.             return response.count();
  391.         } catch (Exception e) {
  392.             log.info(">>>>>>>>>>>>>>>count>>>>>>{}", e);
  393.         }
  394.         return 0;
  395.     }
  396.     /*
  397.      * @description:多值匹配
  398.      * @author:  熟透的蜗牛
  399.      * @date: 2023/1/9 14:39
  400.      * @param index
  401.      * @param field 字段
  402.      * @param dataArgs 数值
  403.      * @param beanClass 转化实体类
  404.      * @param start
  405.      * @param pageSize
  406.      * @return: java.util.List<T>
  407.      **/
  408.     public <T> List<T> termsQuery(String index, String field, List<FieldValue> fieldValues, Class<T> beanClass, Integer start, Integer pageSize) {
  409.         // 查询的数据列表
  410.         List<T> list = new ArrayList<>();
  411.         try {
  412.             TermsQuery termsQuery = TermsQuery.of(terms -> terms.field(field).terms(value -> value.value(fieldValues)));
  413.             SearchResponse<T> response = elasticsearchClient.search(builder ->
  414.                             builder.index(index).query(terms -> terms.terms(termsQuery))
  415.                                     .from((start - 1) * pageSize)
  416.                                     .size(pageSize)
  417.                                     .trackTotalHits(f -> f.enabled(true))
  418.                     , beanClass);
  419.             queryEsData(beanClass, list, response);
  420.         } catch (Exception e) {
  421.             log.info(">>>>>>>>>>>>>>>termsQuery>>>>>>{}", e);
  422.         }
  423.         return list;
  424.     }
  425.     /**
  426.      * @param index
  427.      * @param beanClass
  428.      * @param start
  429.      * @param pageSize
  430.      * @description: match_all查询
  431.      * @return: java.util.List<T>
  432.      * @author 熟透的蜗牛
  433.      * @date: 2025/1/22 0:10
  434.      */
  435.     public <T> List<T> matchAllQuery(String index, Class<T> beanClass, int start, int pageSize) {
  436.         // 查询的数据列表
  437.         List<T> list = new ArrayList<>();
  438.         try {
  439.             SearchResponse<T> searchResponse = elasticsearchClient.search(
  440.                     q -> q.index(index)
  441.                             .query(matchAll -> matchAll
  442.                                     .matchAll(all -> all))
  443.                             .from((start - 1) * pageSize)
  444.                             .size(pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize)
  445.                             .trackTotalHits(f -> f.enabled(true)),
  446.                     beanClass);
  447.             queryEsData(beanClass, list, searchResponse);
  448.         } catch (IOException e) {
  449.             log.info(">>>>>>>>>>>>>>>matchAllQuery>>>>>>{}", e);
  450.         }
  451.         return list;
  452.     }
  453.     /**
  454.      * @param index
  455.      * @param beanClass
  456.      * @param field
  457.      * @param value
  458.      * @description:词组查询
  459.      * @return: java.util.List<T>
  460.      * @author 熟透的蜗牛
  461.      * @date: 2025/1/22 0:08
  462.      */
  463.     public <T> List<T> matchPhraseQuery(String index, Class<T> beanClass, String field, Object value, int start, int pageSize) {
  464.         List<T> list = new ArrayList<>();
  465.         try {
  466.             SearchResponse<T> response = elasticsearchClient.search(q ->
  467.                             q.index(index).query(
  468.                                             pp -> pp.matchPhrase(
  469.                                                     p -> p.field(field)
  470.                                                             .query(String.valueOf(value))))
  471.                                     .from((start - 1) * pageSize)
  472.                                     .size(pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize)
  473.                                     .trackTotalHits(f -> f.enabled(true)),
  474.                     beanClass);
  475.             queryEsData(beanClass, list, response);
  476.         } catch (IOException e) {
  477.             log.info(">>>>>>>>>>>>>>>matchPhraseQuery>>>>>>{}", e);
  478.         }
  479.         return list;
  480.     }
  481.     /*
  482.      * @description:内容在多字段查询
  483.      * @author:  熟透的蜗牛
  484.      * @date: 2023/1/9 15:27
  485.      * @param index
  486.      * @param beanClass
  487.      * @param fields
  488.      * @param text
  489.      * @param start 起始位置
  490.      * @param pageSize 页容量
  491.      * @return: java.util.List<T>
  492.      **/
  493.     public <T> List<T> matchMultiQuery(String index, Class<T> beanClass, String[] fields, Object text, Integer start, Integer pageSize) {
  494.         // 查询的数据列表
  495.         List<T> list = new ArrayList<>();
  496.         try {
  497.             SearchResponse<T> response = elasticsearchClient.search(q -> q.index(index)
  498.                             .query(multiMatch ->
  499.                                     multiMatch.multiMatch(m ->
  500.                                             m.fields(Arrays.asList(fields))
  501.                                                     .query(text.toString())))
  502.                             .from((start - 1) * pageSize)
  503.                             .size(pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize)
  504.                             .trackTotalHits(f -> f.enabled(true)),
  505.                     beanClass);
  506.             queryEsData(beanClass, list, response);
  507.         } catch (Exception e) {
  508.             log.info(">>>>>>>>>>>>>>>matchMultiQuery>>>>>>{}", e);
  509.         }
  510.         return list;
  511.     }
  512.     /*
  513.      * @description: 通配符查询(wildcard):会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) 和 * (0个或多个字符)
  514.      * *:表示多个字符(0个或多个字符)
  515.      * ?:表示单个字符
  516.      * @author:  熟透的蜗牛
  517.      * @date: 2023/1/6 15:02
  518.      * @param index
  519.      * @param beanClass
  520.      * @param field
  521.      * @param text
  522.      * @return: java.util.List<T>
  523.      **/
  524.     public <T> List<T> wildcardQuery(String index, Class<T> beanClass, String field, String text, Integer start, Integer pageSize) {
  525.         // 查询的数据列表
  526.         List<T> list = new ArrayList<>();
  527.         try {
  528.             SearchResponse<T> response = elasticsearchClient.search(q -> q.index(index)
  529.                             .query(wildcard -> wildcard.wildcard(w ->
  530.                                     w.field(field)
  531.                                             .value(text.toString())))
  532.                             .from((start - 1) * pageSize)
  533.                             .size(pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize)
  534.                             .trackTotalHits(f -> f.enabled(true)),
  535.                     beanClass);
  536.             queryEsData(beanClass, list, response);
  537.         } catch (Exception e) {
  538.             log.info(">>>>>>>>>>>>>>>wildcardQuery>>>>>>{}", e);
  539.         }
  540.         return list;
  541.     }
  542.     /**
  543.      * @param index
  544.      * @param beanClass
  545.      * @param field
  546.      * @param text
  547.      * @param start
  548.      * @param pageSize
  549.      * @param prefixLength 指定匹配的前缀长度,前面多少个字符需要完全匹配
  550.      * @param maxExpansion 限制查询扩展的最大数量。用于控制在查询中允许的最大变体数量
  551.      * @description: 模糊匹配
  552.      * @return: java.util.List<T>
  553.      * @author 熟透的蜗牛
  554.      * @date: 2025/1/22 1:02
  555.      */
  556.     public <T> List<T> fuzzyQuery(String index, Class<T> beanClass, String field, String text, Integer start,
  557.                                   Integer pageSize, Integer prefixLength, Integer maxExpansion) {
  558.         // 查询的数据列表
  559.         List<T> list = new ArrayList<>();
  560.         try {
  561.             SearchResponse<T> response = elasticsearchClient.search(q -> q.index(index)
  562.                             .query(fuzzy ->
  563.                                     fuzzy.fuzzy(f ->
  564.                                             f.field(field)
  565.                                                     .value(text.toString())
  566.                                                     .fuzziness("auto")
  567.                                                     .prefixLength(prefixLength)
  568.                                                     .maxExpansions(maxExpansion)))
  569.                             .from((start - 1) * pageSize)
  570.                             .size(pageSize > MAX_PAGE_SIZE ? MAX_PAGE_SIZE : pageSize)
  571.                             .trackTotalHits(f -> f.enabled(true)),
  572.                     beanClass);
  573.             queryEsData(beanClass, list, response);
  574.         } catch (IOException e) {
  575.             log.info(">>>>>>>>>>>>>>>fuzzyQuery>>>>>>{}", e);
  576.         }
  577.         return list;
  578.     }
  579.     /*
  580.      * @description:聚合查询
  581.      * @author:  熟透的蜗牛
  582.      * @date: 2023/1/6 15:34
  583.      * @param index
  584.      * @param type 常用的操作有:avg:求平均、max:最大值、min:最小值、sum:求和
  585.      * @param field
  586.      **/
  587.     public Double metricQuery(String index, String type, String field) {
  588.         try {
  589.             Query query = MatchAllQuery.of(q -> q)._toQuery();
  590.             SearchRequest.Builder searchBuilder = new SearchRequest.Builder().index(index).query(query);
  591.             if (MetricConstant.MAX.equals(type)) {
  592.                 Aggregation max = AggregationBuilders.max(m -> m.field(field));
  593.                 searchBuilder.aggregations("max", max);
  594.             }
  595.             if (MetricConstant.MIN.equals(type)) {
  596.                 Aggregation min = AggregationBuilders.min(m -> m.field(field));
  597.                 searchBuilder.aggregations("min", min);
  598.             }
  599.             if (MetricConstant.AVG.equals(type)) {
  600.                 Aggregation avg = AggregationBuilders.avg(a -> a.field(field));
  601.                 searchBuilder.aggregations("avg", avg);
  602.             }
  603.             if (MetricConstant.SUM.equals(type)) {
  604.                 Aggregation sum = AggregationBuilders.sum(s -> s.field(field));
  605.                 searchBuilder.aggregations("sum", sum);
  606.             }
  607.             SearchResponse searchResponse = elasticsearchClient.search(searchBuilder.build(), Map.class);
  608.             Map aggregations = searchResponse.aggregations();
  609.             if (MetricConstant.MAX.equals(type)) {
  610.                 Aggregate maxAggregate = (Aggregate) aggregations.get(MetricConstant.MAX);
  611.                 MaxAggregate max = (MaxAggregate) maxAggregate._get();
  612.                 return max.value();
  613.             }
  614.             if (MetricConstant.MIN.equals(type)) {
  615.                 Aggregate minAggregate = (Aggregate) aggregations.get(MetricConstant.MIN);
  616.                 MinAggregate min = (MinAggregate) minAggregate._get();
  617.                 return min.value();
  618.             }
  619.             if (MetricConstant.AVG.equals(type)) {
  620.                 Aggregate avgAggregate = (Aggregate) aggregations.get(MetricConstant.AVG);
  621.                 AvgAggregate avg = (AvgAggregate) avgAggregate._get();
  622.                 return avg.value();
  623.             }
  624.             if (MetricConstant.SUM.equals(type)) {
  625.                 Aggregate sumAggregate = (Aggregate) aggregations.get(MetricConstant.SUM);
  626.                 SumAggregate sum = (SumAggregate) sumAggregate._get();
  627.                 return sum.value();
  628.             }
  629.         } catch (Exception e) {
  630.             log.info(">>>>>>>>>>>>>>>metricQuery>>>>>>{}", e);
  631.         }
  632.         return null;
  633.     }
  634.     /**
  635.      * @param index
  636.      * @param bucketField 分组的字段,字段类型为keyword,bucketField分组别名
  637.      * @description: 分组聚合查询,返回map集合
  638.      * @return: java.util.List<java.util.HashMap < java.lang.String, java.lang.Object>>
  639.      * @author 熟透的蜗牛
  640.      * @date: 2025/1/22 14:42
  641.      */
  642.     public List<Map<String, Object>> bucketQuery(String index, String bucketField, String bucketFieldAlias) {
  643.         List<Map<String, Object>> resultMapList = new ArrayList<>();
  644.         try {
  645.             SearchResponse<Void> response = elasticsearchClient.search(q -> q.index(index).query(query -> query.matchAll(all -> all))
  646.                             .aggregations(bucketFieldAlias, agg -> agg.terms(t -> t.field(bucketField))),
  647.                     Void.class);
  648.             Map<String, Aggregate> aggregationsMap = response.aggregations();
  649.             Aggregate aggregate = aggregationsMap.get(bucketFieldAlias);
  650.             StringTermsAggregate stringTermsAggregate = (StringTermsAggregate) aggregate._get();
  651.             Buckets<StringTermsBucket> buckets = stringTermsAggregate.buckets();
  652.             List<StringTermsBucket> list = (List) buckets._get();
  653.             HashMap<String, Object> resulMap = new HashMap<>();
  654.             int i = 0;
  655.             for (StringTermsBucket st : list) {
  656.                 i++;
  657.                 JSONObject jsonObject = new JSONObject();
  658.                 jsonObject.put(st.key()._toJsonString(), st.docCount());
  659.                 resulMap.put(bucketFieldAlias + i, jsonObject);
  660.                 resultMapList.add(resulMap);
  661.             }
  662.         } catch (Exception e) {
  663.             log.info(">>>>>>>>>>>>>>>bucketQuery>>>>>>{}", e);
  664.         }
  665.         return resultMapList;
  666.     }
  667.     /**
  668.      * @param index
  669.      * @param bucketField
  670.      * @param bucketFieldAlias 分组的别名
  671.      * @param avgFiled
  672.      * @param avgFiledAlias    平均值的别名
  673.      * @description: 分组后的聚合
  674.      * @author 熟透的蜗牛
  675.      * @date: 2025/1/22 15:20
  676.      */
  677.     public List<Map<String, Object>> subBucketQuery(String index, String bucketField, String bucketFieldAlias, String avgFiled, String avgFiledAlias) {
  678.         List<Map<String, Object>> resultMapList = new ArrayList<>();
  679.         try {
  680.             SearchResponse<Void> response = elasticsearchClient.search(q -> q.index(index).query(query -> query.matchAll(all -> all))
  681.                             .aggregations(bucketFieldAlias, agg -> agg.terms(t -> t.field(bucketField))
  682.                                     .aggregations(avgFiledAlias, avg -> avg.avg(a -> a.field(avgFiled))))
  683.                     , Void.class);
  684.             Map<String, Aggregate> aggregations = response.aggregations();
  685.             log.info(">>>>>>>>>>>>aggregations{}", aggregations);
  686.             Aggregate aggregate = aggregations.get(bucketFieldAlias);
  687.             StringTermsAggregate stringTermsAggregate = (StringTermsAggregate) aggregate._get();
  688.             List<StringTermsBucket> list = (List<StringTermsBucket>) stringTermsAggregate.buckets()._get();
  689.             int i = 0;
  690.             for (StringTermsBucket st : list) {
  691.                 HashMap<String, Object> resultMap = new HashMap<>();
  692.                 JSONObject jsonObject = new JSONObject();
  693.                 Aggregate avgAggregate = st.aggregations().get(avgFiledAlias); //从聚合中取平均值
  694.                 AvgAggregate avg = (AvgAggregate) avgAggregate._get();
  695.                 jsonObject.put(st.key()._toJsonString(), st.docCount());
  696.                 jsonObject.put(avgFiledAlias, avg.value());
  697.                 resultMap.put(bucketFieldAlias + i, jsonObject);
  698.                 resultMapList.add(resultMap);
  699.             }
  700.         } catch (Exception e) {
  701.             log.info(">>>>>>>>>>>>>>>subBucketQuery>>>>>>{}", e);
  702.         }
  703.         return resultMapList;
  704.     }
  705.     /**
  706.      * @param beanClass
  707.      * @param list
  708.      * @param searchResponse
  709.      * @description: 封装返回数据
  710.      * @return: void
  711.      * @author 熟透的蜗牛
  712.      * @date: 2025/1/15 23:58
  713.      */
  714.     private <T> void queryEsData(Class<T> beanClass, List<T> list, SearchResponse<T> searchResponse)
  715.             throws IOException {
  716.         if (searchResponse.hits().total().value() > 0) {
  717.             List<Hit<T>> hitList = searchResponse.hits().hits();
  718.             for (Hit hit : hitList) {
  719.                 // 将 JSON 转换成对象
  720.                 T bean = JSON.parseObject(JSON.toJSONString(hit.source()), beanClass);
  721.                 list.add(bean);
  722.             }
  723.         }
  724.     }
  725. }
复制代码
二、测试代码

  1. package com.snail.system.controller;
  2. import co.elastic.clients.elasticsearch._types.FieldValue;
  3. import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
  4. import co.elastic.clients.elasticsearch._types.query_dsl.MultiMatchQuery;
  5. import co.elastic.clients.elasticsearch._types.query_dsl.Query;
  6. import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
  7. import co.elastic.clients.elasticsearch.core.search.Hit;
  8. import co.elastic.clients.json.JsonData;
  9. import com.alibaba.fastjson2.JSON;
  10. import com.alibaba.fastjson2.JSONObject;
  11. import com.snail.manager.common.utils.ValidateCodeUtils;
  12. import com.snail.system.service.user.User;
  13. import com.wssnail.elasticsearch.util.ElasticSearchUtils;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.util.CollectionUtils;
  17. import org.springframework.web.bind.annotation.GetMapping;
  18. import org.springframework.web.bind.annotation.RestController;
  19. import java.util.*;
  20. /**
  21. * @author 熟透的蜗牛
  22. * @version 1.0
  23. * @description: TODO
  24. * @date 2025/1/16 20:20
  25. */
  26. @RestController
  27. @Slf4j
  28. public class DemoController {
  29.     @Autowired
  30.     private ElasticSearchUtils elasticSearchUtils;
  31.     @GetMapping("/demo")
  32.     public String test(int type) {
  33.         switch (type) {
  34.             case 1:
  35.                 log.info("create......{}", elasticSearchUtils.createIndex("user_index"));
  36.                 break;
  37.             case 2:
  38.                 log.info("delete......{}", elasticSearchUtils.deleteIndex("user_index"));
  39.                 break;
  40.             case 3:
  41.                 log.info("isIndexExist......{}", elasticSearchUtils.isIndexExist("user_index"));
  42.                 break;
  43.             case 4:
  44.                 for (int i = 0; i < 1000; i++) {
  45.                     User user = new User();
  46.                     user.setId("10000" + i);
  47.                     user.setName("tom" + i + ValidateCodeUtils.generateLetter(6));
  48.                     user.setAge((int) (Math.random() * 100));
  49.                     if (i < 50) {
  50.                         user.setAddress("北京市东城区1号路");
  51.                         user.setBirthday(new Date("1990/03/01 00:00:00"));
  52.                     }
  53.                     if (i > 50 && i < 100) {
  54.                         user.setAddress("北京市西城区88号路");
  55.                         user.setBirthday(new Date("1998/03/01 00:00:00"));
  56.                     }
  57.                     if (i > 100 && i < 200) {
  58.                         user.setAddress("北京市朝阳区青年路100号");
  59.                         user.setBirthday(new Date("2000/03/01 00:00:00"));
  60.                     }
  61.                     if (i > 200 && i < 500) {
  62.                         user.setAddress("天津市和平区青年路100号");
  63.                         user.setBirthday(new Date("2005/08/01 00:00:00"));
  64.                     }
  65.                     if (i > 500 && i < 800) {
  66.                         user.setAddress("天津市河西区青年路88号");
  67.                     }
  68.                     if (i > 800) {
  69.                         user.setAddress("石家庄市桥西区青年路100号");
  70.                     }
  71.                     String id = elasticSearchUtils.submitDocument(user, "user_index", user.getId());
  72.                     log.info("id:{}", id);
  73.                 }
  74.                 break;
  75.             case 5:
  76.                 log.info("是否存在数据>>>>{}", elasticSearchUtils.existsById("user_index", "1000035"));
  77.                 break;
  78.             case 6:
  79.                 log.info("根据地删除数据>>>>{}", elasticSearchUtils.deleteDocumentById("user_index", "1000036"));
  80.                 break;
  81.             case 7:
  82.                 User user = new User("tom356666666", 20, "上海市闸北区霞飞路66号");
  83.                 log.info("根据id修改数据>>>>>{}", elasticSearchUtils.updateDocumentById(user, "user_index", "1000035"));
  84.                 break;
  85.             case 8:
  86.                 log.info("时实修改数据>>>>>>>{}", elasticSearchUtils.updateDocumentByIdNoRealTime(User.builder().name("66666666").build(), "user_index", "1000037"));
  87.                 break;
  88.             case 9:
  89.                 log.info("根据id查询数据>>>>>{}", JSON.to(User.class, elasticSearchUtils.searchDocumentById("user_index", "1000035", new ArrayList<>(), new ArrayList<>())));
  90.                 break;
  91.             case 10:
  92.                 log.info("根据id查询数据返回指定字段>>>>>{}", JSON.to(User.class, elasticSearchUtils.searchDocumentById("user_index", "1000035", Arrays.asList("name", "address"), new ArrayList<>())));
  93.                 break;
  94.             case 11:
  95.                 //批量插入
  96.                 ArrayList<Map> mapList = new ArrayList<>();
  97.                 for (int i = 0; i < 100; i++) {
  98.                     HashMap<Object, Object> userMap = new HashMap<>();
  99.                     User user1 = new User();
  100.                     user1.setId("1000000" + i);
  101.                     user1.setName(ValidateCodeUtils.generateLetter(10));
  102.                     user1.setAge((int) (Math.random() * 100));
  103.                     user1.setAddress("南京市淮河区夫子庙35号");
  104.                     user1.setBirthday(new Date("2010/10/01 00:00:00"));
  105.                     userMap.put("data", user1);
  106.                     userMap.put("id", user1.getId());
  107.                     mapList.add(userMap);
  108.                 }
  109.                 log.info(">>>>>>>>>>>>>>>批量插入结果{}", elasticSearchUtils.bulkPost("user_index", mapList));
  110.                 break;
  111.             case 12:
  112. //                Query termQuery = TermQuery.of(t -> t.field("address").value("北京"))._toQuery();
  113. //                Query rangeQuery = RangeQuery.of(age -> age.field("age").gte(JsonData.of(60)))._toQuery();
  114.                 Query multiQuery = MultiMatchQuery.of(m -> m.fields("address").query("南京"))._toQuery();
  115.                 String[] highlightField = {"address"};
  116.                 List<Hit<Map>> hits = elasticSearchUtils.searchHighLightFieldDocument("user_index", highlightField, 1, 20, multiQuery);
  117.                 List<User> result = new ArrayList<>();
  118.                 for (Hit<Map> hit : hits) {
  119.                     Map source = hit.source();
  120.                     User userResult = JSONObject.parseObject(JSONObject.toJSONString(source), User.class);
  121.                     Map<String, List<String>> highlight = hit.highlight();
  122.                     userResult.setAddress(CollectionUtils.isEmpty(highlight.get("address")) ? userResult.getAddress() : highlight.get("address").get(0));
  123.                     userResult.setAge(CollectionUtils.isEmpty(highlight.get("age")) ? userResult.getAge() : Integer.valueOf(highlight.get("age").get(0)));
  124.                     result.add(userResult);
  125.                 }
  126.                 log.info(">>>>>>>>>>>>>>>>>数据结果{}", result);
  127.                 break;
  128.             case 13:
  129.                 log.info(">>>>>>>>精确查询结果{}", elasticSearchUtils.termQuery("user_index", "address", "北京市东城区1号路", User.class, 1, 30));
  130.                 break;
  131.             case 14:
  132.                 //自定义查询
  133.                 Query boolQuery = BoolQuery.of(b -> b.must(name -> name.term(n -> n.field("name.keyword").value("tom38ictwvq")))
  134.                         .must(m -> m.range(age -> age.field("age").gte(JsonData.of(60)).lte(JsonData.of(80))))
  135.                         .should(s -> s.term(address -> address.field("address").value("南京市淮河区夫子庙35号"))))._toQuery();
  136.                 log.info(">>>>>>>>>>自定义查询{}", elasticSearchUtils.selfDefine("user_index", User.class, boolQuery));
  137.                 break;
  138.             case 15:
  139.                 //查询文档数量
  140.                 Query ageQuery = TermQuery.of(t -> t.field("age").value("63"))._toQuery();
  141.                 log.info(">>>>>>>>文档数量{}", elasticSearchUtils.count("user_index", ageQuery));
  142.                 break;
  143.             case 16:
  144.                 List<FieldValue> list = new ArrayList<>();
  145.                 list.add(FieldValue.of("tom58dhmceA"));
  146.                 list.add(FieldValue.of("tom38ictwvq"));
  147.                 log.info(">>>>>>>多值查询{}", elasticSearchUtils.termsQuery("user_index", "name.keyword", list, User.class, 1, 20));
  148.                 break;
  149.             case 17:
  150.                 log.info(">>>>>>>>>匹配所有{}", elasticSearchUtils.matchAllQuery("user_index", User.class, 1, 20));
  151.                 break;
  152.             case 18:
  153.                 log.info(">>>>>>>>>phrase匹配{}", elasticSearchUtils.matchPhraseQuery("user_index", User.class, "address", "南京", 1, 20));
  154.                 break;
  155.             case 19:
  156.                 log.info(">>>>>>>>>多字段匹配{}", elasticSearchUtils.matchMultiQuery("user_index", User.class, new String[]{"address", "age"}, "88", 1, 20));
  157.                 break;
  158.             case 20:
  159.                 log.info("wildcardQuery>>>>>>{}", elasticSearchUtils.wildcardQuery("user_index", User.class, "name", "tom*", 1, 20));
  160.                 break;
  161.             case 21:
  162.                 log.info("fuzzyQuery>>>>>>{}", elasticSearchUtils.fuzzyQuery("user_index", User.class, "name", "tom38ictvq", 1, 20, 5, 5));
  163.                 break;
  164.             case 22:
  165.                 log.info("avg>>>>>>{}", elasticSearchUtils.metricQuery("user_index", "avg", "age"));
  166.                 log.info("max>>>>>>{}", elasticSearchUtils.metricQuery("user_index", "max", "age"));
  167.                 log.info("min>>>>>>{}", elasticSearchUtils.metricQuery("user_index", "min", "age"));
  168.                 log.info("sum>>>>>>{}", elasticSearchUtils.metricQuery("user_index", "sum", "age"));
  169.                 break;
  170.             case 23:
  171.                 log.info("聚合分组查询>>>>>>>{}", elasticSearchUtils.bucketQuery("user_index", "address.keyword", "address"));
  172.                 break;
  173.             case 24:
  174.                 log.info(">>>>>>分组后的聚合查询>>{}", elasticSearchUtils.subBucketQuery("user_index", "address.keyword", "address", "age", "age_avg"));
  175.                 break;
  176.             default:
  177.                 break;
  178.         }
  179.         return "success";
  180.     }
  181. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表