当前位置:   article > 正文

Java与Elasticsearch的API实现工具类(一)——条件查询_java 查询接口通用条件对象

java 查询接口通用条件对象

相关代码已上传gitee

https://gitee.com/gangye/elasticsearch_demo

首先搭建一个项目,引入pom依赖,引入es的相关jar包

  1. <!--引入elasticsearch相关jar包-->
  2. <dependency>
  3. <groupId>org.elasticsearch.client</groupId>
  4. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  5. <version>6.8.8</version>
  6. <exclusions>
  7. <exclusion>
  8. <groupId>org.elasticsearch</groupId>
  9. <artifactId>elasticsearch</artifactId>
  10. </exclusion>
  11. </exclusions>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.elasticsearch.client</groupId>
  15. <artifactId>elasticsearch-rest-client</artifactId>
  16. <version>6.8.8</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.elasticsearch</groupId>
  20. <artifactId>elasticsearch</artifactId>
  21. <version>6.8.8</version>
  22. </dependency>

在application.yml中配置相关属性值,此处使用的es的集群地址是本地多个虚拟机启动的集群模式

  1. elasticsearch:
  2. config:
  3. host: 192.168.236.131:9200,192.168.236.130:9200,192.168.236.129:9200
  4. requestType: csrcb
  5. connectTimeout: 1000
  6. socketTimeout: 5000
  7. maxRetryTimeout: 5000
  8. connRequestTimeOut: 1000

定义配置类获取配置文件的属性值

  1. package com.csrcb.config;
  2. import lombok.Data;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.context.annotation.Configuration;
  5. /**
  6. * @Classname EsClientConfig
  7. * @Description 获取es的相关配置属性,以及属性值
  8. * @Date 2021/6/2 17:30
  9. * @Created by gangye
  10. */
  11. @Configuration
  12. @Data
  13. public class EsClientConfig {
  14. @Value("${elasticsearch.config.host}")
  15. private String hosts;
  16. @Value("${elasticsearch.config.connectTimeout}")
  17. private int connectTimeout;
  18. @Value("${elasticsearch.config.socketTimeout}")
  19. private int socketTimeout;
  20. @Value("${elasticsearch.config.maxRetryTimeout}")
  21. private int maxRetryTimeout;
  22. @Value("${elasticsearch.config.connRequestTimeOut}")
  23. private int connRequestTimeOut;
  24. }

 定义es的客户端连接

  1. package com.csrcb.config;
  2. import com.csrcb.common.DefineConstant;
  3. import org.apache.http.HttpHost;
  4. import org.apache.http.client.config.RequestConfig;
  5. import org.elasticsearch.client.RestClient;
  6. import org.elasticsearch.client.RestClientBuilder;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import java.util.ArrayList;
  9. import java.util.Arrays;
  10. import java.util.List;
  11. /**
  12. * @Classname EsClient
  13. * @Description es的客户端连接
  14. * @Date 2021/6/3 9:24
  15. * @Created by gangye
  16. */
  17. public class EsClient {
  18. public static String hosts;
  19. public static int connectTimeout;
  20. public static int socketTimeout;
  21. public static int maxRetryTimeout;
  22. public static int connRequestTimeOut;
  23. private static RestHighLevelClient restHighLevelClient = null;
  24. public EsClient(){
  25. EsClientConfig esClientConfig = new EsClientConfig();
  26. hosts = esClientConfig.getHosts();
  27. connectTimeout = esClientConfig.getConnectTimeout();
  28. socketTimeout = esClientConfig.getSocketTimeout();
  29. maxRetryTimeout = esClientConfig.getMaxRetryTimeout();
  30. connRequestTimeOut = esClientConfig.getConnRequestTimeOut();
  31. }
  32. public static RestHighLevelClient getInstance(){
  33. if (restHighLevelClient == null){
  34. synchronized (RestHighLevelClient.class){
  35. restHighLevelClient = createClient();
  36. }
  37. }
  38. return restHighLevelClient;
  39. }
  40. private static RestHighLevelClient createClient(){
  41. List<String> sockets = Arrays.asList(hosts.split(DefineConstant.COMMAN_SIGN));
  42. List<HttpHost> httpHosts = new ArrayList<>();
  43. for (String socket : sockets){
  44. httpHosts.add(new HttpHost(socket.split(DefineConstant.COLON_SIGN)[0], Integer.valueOf(socket.split(DefineConstant.COLON_SIGN)[1]),"http"));
  45. }
  46. RestClientBuilder builder = RestClient.builder(httpHosts.toArray(new HttpHost[0])).setMaxRetryTimeoutMillis(maxRetryTimeout);
  47. builder.setRequestConfigCallback((RequestConfig.Builder requestConfigBuilder) -> {
  48. requestConfigBuilder.setConnectTimeout(connectTimeout);
  49. requestConfigBuilder.setConnectionRequestTimeout(connRequestTimeOut);
  50. requestConfigBuilder.setSocketTimeout(socketTimeout);
  51. return requestConfigBuilder;
  52. });
  53. restHighLevelClient = new RestHighLevelClient(builder);
  54. return restHighLevelClient;
  55. }
  56. }

 定义常量值

  1. package com.csrcb.common;
  2. /**
  3. * @Classname DefineConstant
  4. * @Description 定义一些常量值
  5. * @Date 2021/6/3 10:00
  6. * @Created by gangye
  7. */
  8. public class DefineConstant {
  9. /**
  10. * 逗号分隔符
  11. */
  12. public static final String COMMAN_SIGN = ",";
  13. /**
  14. * 等号分隔符
  15. */
  16. public static final String EQUALITY_SIGN = "=";
  17. /**
  18. * 冒号分隔符
  19. */
  20. public static final String COLON_SIGN = ":";
  21. /**
  22. * es的索引文档类型
  23. */
  24. public static final String SEARCH_REQUEST_TYPE = "csrcb";
  25. //区间左闭
  26. public static final String INTERVAL_CLOSE_LEFT = "[";
  27. //区间右闭
  28. public static final String INTERVAL_CLOSE_RIGHT = "]";
  29. //区间左开
  30. public static final String INTERVAL_OPEN_LEFT = "(";
  31. //区间右开
  32. public static final String INTERVAL_OPEN_RIGHT = ")";
  33. public static final String INTERVAL_OPEN_VALUE = "open";
  34. public static final String INTERVAL_CLOSE_VALUE = "close";
  35. public static final String ZERP_MONEY = "0.00";
  36. }

 查询的工具类,支持多条件等值查询,区间范围查询,模糊查询

  1. /**
  2. * @Description ElasticSearch条件查询
  3. * @param tableName (索引名)也可以类似的说成表名
  4. * @param equalsCondition 关键字等值条件
  5. * 若是一个字符串以%结尾,则匹配以去掉%的字符串开头的记录
  6. * 若是一个字符串以*开头或结尾,则模糊匹配去掉*的记录 类似于sql中的like '%str%'
  7. * 若传入的是一个普通的字符串,则等值查询
  8. * 若传入的是一个集合,则使用的是in条件查询
  9. * @param rangeCondition 条件范围查询
  10. * 字段,字段对应值的区间,区间格式[,]/(,)/[,)/(,],逗号的左右可以没值
  11. * @param orderBy 排序字段
  12. * 若是字段以中划线-开头,则使用降序排序,类似于sql中的desc
  13. * 若正常字段排序,则使用增序排序,类似于sql中的asc
  14. * @param pageNum 页数
  15. * @param pageSize 每页大小
  16. * @return
  17. */
  18. public static Map<String ,Object> queryForEs(String tableName, Map<String, Object> equalsCondition, Map<String, Object> rangeCondition, List<String> orderBy, int pageNum, int pageSize){
  19. Map<String, Object> resultMap = new HashMap<>(8);
  20. List<Map<String,Object>> queryResult = new ArrayList<>();
  21. long totalNum = 0;
  22. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  23. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  24. // and 等值查询
  25. // 某一field=具体的值; 也可以某一field 的值 in 具体定义集合里的值
  26. if (null != equalsCondition && !equalsCondition.isEmpty()){
  27. for (Map.Entry<String ,Object> entry : equalsCondition.entrySet()){
  28. String key = entry.getKey();
  29. //由于我创建索引的时候使用字符串不分词使用的.keyword类型
  30. if (key.endsWith("_s")){
  31. queryValueBuild(boolQueryBuilder, key + ".keyword", entry.getValue());
  32. }else{
  33. queryValueBuild(boolQueryBuilder, key, entry.getValue());
  34. }
  35. }
  36. }
  37. //范围查询
  38. if (null != rangeCondition && !rangeCondition.isEmpty()){
  39. rangeValueBuild(boolQueryBuilder, rangeCondition);
  40. }
  41. sourceBuilder.query(boolQueryBuilder);
  42. //排序
  43. if (null != orderBy && !orderBy.isEmpty()){
  44. buildSort(sourceBuilder, orderBy);
  45. }
  46. //分页(es分页查询默认是查询返回10条记录,而深度分页,默认是10000条数据,也就是一次性最多返回10000条,设置size就可以实现,但是如果实际数据量特别大,可以使用scroll游标查询,此处主要常规分页查询)
  47. if (pageNum > 0){
  48. sourceBuilder.from(pageSize * (pageNum - 1));
  49. } else {
  50. sourceBuilder.from(0);
  51. }
  52. sourceBuilder.size(pageSize);
  53. //执行查询
  54. SearchResponse response = executeSearch(tableName, sourceBuilder);
  55. SearchHits searchHits = response.getHits();
  56. SearchHit[] hits = searchHits.getHits();
  57. totalNum = searchHits.getTotalHits();
  58. for (int i = 0; i < hits.length; i++){
  59. SearchHit hit = hits[i];
  60. Map<String, Object> sourceMap= hit.getSourceAsMap();
  61. sourceMap.put("id_s", hit.getId());
  62. queryResult.add(sourceMap);
  63. }
  64. resultMap.put("pageList", queryResult);
  65. resultMap.put("totalNum", totalNum);
  66. resultMap.put("pageNum", pageNum);
  67. resultMap.put("pageSize", pageSize);
  68. return resultMap;
  69. }
  70. /**
  71. * @Description 查询条件组装
  72. * @param boolQueryBuilder
  73. * @param key
  74. * @param value
  75. */
  76. private static void queryValueBuild(BoolQueryBuilder boolQueryBuilder, String key, Object value){
  77. TermQueryBuilder termQueryBuilder;
  78. if (null != value && !"".equals(value)){
  79. if (value instanceof String){
  80. String strValue = (String) value;
  81. if (strValue.endsWith("%")){
  82. PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery(key,strValue.replace("%",""));
  83. boolQueryBuilder.must(prefixQueryBuilder);
  84. }else if (strValue.startsWith("*") || strValue.endsWith("*")){
  85. MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(key, strValue.replace("*",""));
  86. boolQueryBuilder.must(matchQueryBuilder);
  87. }else {
  88. termQueryBuilder = QueryBuilders.termQuery(key, strValue);
  89. boolQueryBuilder.must(termQueryBuilder);
  90. }
  91. } else if (value instanceof Collection){
  92. Collection<? extends Object> collectionValue = (Collection<? extends Object>) value;
  93. //此处使用了多值条件
  94. boolQueryBuilder.must(QueryBuilders.termsQuery(key, collectionValue));
  95. } else {
  96. termQueryBuilder = QueryBuilders.termQuery(key, value);
  97. boolQueryBuilder.must(termQueryBuilder);
  98. }
  99. }
  100. }
  101. /**
  102. * @Description 范围条件查询组装
  103. * @param boolQueryBuilder
  104. * @param rangeCondition
  105. */
  106. private static void rangeValueBuild(BoolQueryBuilder boolQueryBuilder, Map<String, Object> rangeCondition){
  107. for (Map.Entry<String, Object> entry : rangeCondition.entrySet()){
  108. Map<String, Object> range = intervalParse((String) entry.getValue());
  109. String key = entry.getKey();
  110. RangeQueryBuilder rangeQueryBuilder;
  111. if (key.endsWith("_s")){
  112. rangeQueryBuilder = QueryBuilders.rangeQuery(key + ".keyword");
  113. }else {
  114. rangeQueryBuilder = QueryBuilders.rangeQuery(key);
  115. }
  116. if (!StringUtils.isEmpty(range.get("leftValue"))){
  117. if (DefineConstant.INTERVAL_OPEN_VALUE.equals(range.get("leftType"))){
  118. rangeQueryBuilder.from(range.get("leftValue"),false);
  119. } else if (DefineConstant.INTERVAL_CLOSE_VALUE.equals(range.get("leftType"))){
  120. rangeQueryBuilder.from(range.get("leftValue"),true);
  121. }
  122. }
  123. if (!StringUtils.isEmpty(range.get("rightValue"))){
  124. if (DefineConstant.INTERVAL_OPEN_VALUE.equals(range.get("rightType"))){
  125. rangeQueryBuilder.to(range.get("rightValue"),false);
  126. } else if (DefineConstant.INTERVAL_CLOSE_VALUE.equals(range.get("rightType"))){
  127. rangeQueryBuilder.to(range.get("rightValue"),true);
  128. }
  129. }
  130. boolQueryBuilder.must(rangeQueryBuilder);
  131. }
  132. }
  133. /**
  134. * @Description 区间解析:[,]/(,)/[,)/(,]
  135. * @param interval
  136. * @return
  137. */
  138. private static Map<String, Object> intervalParse(String interval){
  139. Map<String, Object> range = new HashMap<>();
  140. if (interval.startsWith(DefineConstant.INTERVAL_CLOSE_LEFT)){
  141. range.put("leftType", DefineConstant.INTERVAL_CLOSE_VALUE);
  142. } else if (interval.startsWith(DefineConstant.INTERVAL_OPEN_LEFT)){
  143. range.put("leftType", DefineConstant.INTERVAL_OPEN_VALUE);
  144. } else{
  145. log.error("区间参数格式错误:{}",interval);
  146. //若实际业务相关需要,抛出异常处理throw new Exception();
  147. }
  148. if (interval.endsWith(DefineConstant.INTERVAL_CLOSE_RIGHT)){
  149. range.put("rightType", DefineConstant.INTERVAL_CLOSE_VALUE);
  150. } else if (interval.startsWith(DefineConstant.INTERVAL_OPEN_RIGHT)){
  151. range.put("rightType", DefineConstant.INTERVAL_OPEN_VALUE);
  152. } else{
  153. log.error("区间参数格式错误:{}",interval);
  154. //若实际业务相关需要,抛出异常处理throw new Exception();
  155. }
  156. int strLen = interval.length();
  157. String[] lr = interval.substring(1, strLen - 1).split(DefineConstant.COMMAN_SIGN, 2);
  158. if (lr.length > 0){
  159. range.put("leftValue", lr[0]);
  160. }
  161. if (lr.length > 1){
  162. range.put("rightValue", lr[1]);
  163. }
  164. return range;
  165. }
  166. /**
  167. * @Description 查询排序
  168. * @param sourceBuilder
  169. * @param orderBy
  170. */
  171. private static void buildSort(SearchSourceBuilder sourceBuilder, List<String> orderBy){
  172. SortBuilder<FieldSortBuilder> sortBuilder;
  173. for (String sortField : orderBy){
  174. if (sortField.startsWith("-")){
  175. //降序排序
  176. if (sortField.endsWith("_s")){
  177. sortBuilder = SortBuilders.fieldSort(sortField.replace("-","") + ".keyword").order(SortOrder.DESC);
  178. } else {
  179. sortBuilder = SortBuilders.fieldSort(sortField.replace("-","")).order(SortOrder.DESC);
  180. }
  181. } else {
  182. //升序排序
  183. if (sortField.endsWith("_s")){
  184. sortBuilder = SortBuilders.fieldSort(sortField.replace("-","") + ".keyword").order(SortOrder.ASC);
  185. } else {
  186. sortBuilder = SortBuilders.fieldSort(sortField.replace("-","")).order(SortOrder.ASC);
  187. }
  188. }
  189. sourceBuilder.sort(sortBuilder);
  190. }
  191. }
  192. /**
  193. * @Description 执行查询
  194. * @param tableName 对应的es的index名
  195. * @param sourceBuilder
  196. * @return
  197. */
  198. private static SearchResponse executeSearch(String tableName, SearchSourceBuilder sourceBuilder){
  199. // 获取不同系统的换行符
  200. String lineSeparator = System.lineSeparator();
  201. log.info(lineSeparator + "index:" + tableName + lineSeparator + "search:"+ sourceBuilder.toString() + lineSeparator);
  202. RestHighLevelClient client = EsClient.getInstance();
  203. SearchRequest searchRequest = new SearchRequest(tableName);
  204. SearchResponse response = null;
  205. //设置查询的文档代表的对象的类,即type(此处我写死固定值,可以自行定义)
  206. searchRequest.types(DefineConstant.SEARCH_REQUEST_TYPE);
  207. searchRequest.source(sourceBuilder);
  208. try {
  209. response = client.search(searchRequest, RequestOptions.DEFAULT);
  210. log.info("search status:{}, totalNum:{}",response.status(), response.getHits().getTotalHits());
  211. } catch (IOException e) {
  212. //异常处理,实际业务中是需要根据需求具体处理,自定义异常捕获
  213. log.error(e.getMessage());
  214. }
  215. return response;
  216. }

例如查询trade_info索引中客户号为10005,交易金额在200以内(包含200)的记录,并按交易时间倒序排序查询

 控制台打印以及查询结果

而通过工具查询的记录:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/68062
推荐阅读
相关标签
  

闽ICP备14008679号