ElasticSearch7Util.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. package com.yihu.jw.elasticsearch;
  2. import com.alibaba.druid.sql.ast.SQLExpr;
  3. import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
  4. import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
  5. import com.alibaba.druid.sql.parser.ParserException;
  6. import com.alibaba.druid.sql.parser.SQLExprParser;
  7. import com.alibaba.druid.sql.parser.Token;
  8. import org.apache.commons.lang3.StringUtils;
  9. import org.apache.http.HttpHost;
  10. import org.elasticsearch.action.search.SearchRequest;
  11. import org.elasticsearch.action.search.SearchRequestBuilder;
  12. import org.elasticsearch.action.search.SearchResponse;
  13. import org.elasticsearch.action.search.SearchType;
  14. import org.elasticsearch.client.Client;
  15. import org.elasticsearch.client.RequestOptions;
  16. import org.elasticsearch.client.RestClient;
  17. import org.elasticsearch.client.RestHighLevelClient;
  18. import org.elasticsearch.client.transport.TransportClient;
  19. import org.elasticsearch.index.query.*;
  20. import org.elasticsearch.search.SearchHit;
  21. import org.elasticsearch.search.SearchHits;
  22. import org.elasticsearch.search.builder.SearchSourceBuilder;
  23. import org.elasticsearch.search.sort.SortBuilder;
  24. import org.nlpcn.es4sql.domain.Select;
  25. import org.nlpcn.es4sql.domain.Where;
  26. import org.nlpcn.es4sql.exception.SqlParseException;
  27. import org.nlpcn.es4sql.jdbc.ObjectResult;
  28. import org.nlpcn.es4sql.jdbc.ObjectResultsExtractor;
  29. import org.nlpcn.es4sql.parse.ElasticSqlExprParser;
  30. import org.nlpcn.es4sql.parse.SqlParser;
  31. import org.nlpcn.es4sql.parse.WhereParser;
  32. import org.nlpcn.es4sql.query.AggregationQueryAction;
  33. import org.nlpcn.es4sql.query.DefaultQueryAction;
  34. import org.nlpcn.es4sql.query.SqlElasticSearchRequestBuilder;
  35. import org.nlpcn.es4sql.query.maker.QueryMaker;
  36. import org.slf4j.Logger;
  37. import org.slf4j.LoggerFactory;
  38. import org.springframework.beans.BeanUtils;
  39. import org.springframework.beans.factory.annotation.Autowired;
  40. import org.springframework.beans.factory.config.ConfigurableBeanFactory;
  41. import org.springframework.context.annotation.Scope;
  42. import org.springframework.stereotype.Service;
  43. import javax.annotation.Resource;
  44. import java.io.IOException;
  45. import java.text.DecimalFormat;
  46. import java.util.*;
  47. /**
  48. * elasticsearch7.x版本数据获取
  49. * Created by yeshijie on 2022/6/15.
  50. */
  51. @Service
  52. @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
  53. public class ElasticSearch7Util {
  54. private static final Logger logger = LoggerFactory.getLogger(ElasticSearch7Util.class);
  55. @Resource(name="esClient")
  56. private RestHighLevelClient restHighLevelClient;
  57. /**
  58. * 执行sql
  59. * @param sql
  60. * @return
  61. */
  62. public Long executeCountSQL(String sql) throws Exception {
  63. //实例化查询请求对象
  64. SearchRequest request = new SearchRequest();
  65. //实例化SearchSourceBuilder
  66. SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
  67. //根据索引、查询条件构建查询构造器
  68. BoolQueryBuilder boolQueryBuilder = createQueryBuilderBySql(sql);
  69. //将查询构造器注入SearchSourceBuilder
  70. searchBuilder.query(boolQueryBuilder);
  71. //设置请求查询的索引(查询构造器中已指定,无需重复设置)
  72. //request.indices(indexName);
  73. //将构建好的SearchSourceBuilder注入请求
  74. request.source(searchBuilder);
  75. //带入请求执行查询
  76. SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  77. //得到查询结果
  78. SearchHits hits = searchResponse.getHits();
  79. SearchHit[] searchHits = hits.getHits();
  80. //遍历查询结果
  81. for(SearchHit hit : searchHits){
  82. Map<String,Object> datas = hit.getSourceAsMap();
  83. for (Object o:datas.values()){
  84. if (o instanceof Double){
  85. Double valueTemp =Double.valueOf((Double)o);
  86. DecimalFormat df = new DecimalFormat("######0");
  87. return Long.parseLong(df.format(valueTemp));
  88. }
  89. }
  90. }
  91. return 0L;
  92. }
  93. /**
  94. * 执行sql
  95. */
  96. public List<Map<String,Object>> executeSQL(String sql) throws IOException {
  97. //实例化查询请求对象
  98. SearchRequest request = new SearchRequest();
  99. //实例化SearchSourceBuilder
  100. SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
  101. //根据索引、查询条件构建查询构造器
  102. BoolQueryBuilder boolQueryBuilder = createQueryBuilderBySql(sql);
  103. //将查询构造器注入SearchSourceBuilder
  104. searchBuilder.query(boolQueryBuilder);
  105. //设置请求查询的索引(查询构造器中已指定,无需重复设置)
  106. //request.indices(indexName);
  107. //将构建好的SearchSourceBuilder注入请求
  108. request.source(searchBuilder);
  109. //带入请求执行查询
  110. SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  111. //得到查询结果
  112. SearchHits hits = searchResponse.getHits();
  113. SearchHit[] searchHits = hits.getHits();
  114. List<Map<String,Object>> listData = new ArrayList<>();
  115. //遍历查询结果
  116. for(SearchHit hit : searchHits){
  117. Map<String,Object> datas = hit.getSourceAsMap();
  118. listData.add(datas);
  119. logger.info(datas.toString());
  120. }
  121. return listData;
  122. }
  123. /**
  124. * 执行sql
  125. */
  126. public <T> List<T> executeSql(String sql,Class<T> clazz) throws Exception {
  127. //实例化查询请求对象
  128. SearchRequest request = new SearchRequest();
  129. //实例化SearchSourceBuilder
  130. SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
  131. //根据索引、查询条件构建查询构造器
  132. BoolQueryBuilder boolQueryBuilder = createQueryBuilderBySql(sql);
  133. //将查询构造器注入SearchSourceBuilder
  134. searchBuilder.query(boolQueryBuilder);
  135. //设置请求查询的索引(查询构造器中已指定,无需重复设置)
  136. //request.indices(indexName);
  137. //将构建好的SearchSourceBuilder注入请求
  138. request.source(searchBuilder);
  139. //带入请求执行查询
  140. SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  141. //得到查询结果
  142. SearchHits hits = searchResponse.getHits();
  143. SearchHit[] searchHits = hits.getHits();
  144. List<T> listData = new ArrayList<>();
  145. //遍历查询结果
  146. for(SearchHit hit : searchHits){
  147. Map<String,Object> datas = hit.getSourceAsMap();
  148. T t = clazz.newInstance();
  149. BeanUtils.copyProperties(t,datas);
  150. listData.add(t);
  151. logger.info(datas.toString());
  152. }
  153. return listData;
  154. }
  155. /**
  156. * 构建查询构造器
  157. * @param indexName 索引名
  158. * @param whereExpress 查询条件:(f1=2 and f2=1) or (f3=1 and f4=1)
  159. * @return
  160. */
  161. public BoolQueryBuilder createQueryBuilderByWhere(String indexName, String whereExpress) {
  162. BoolQueryBuilder boolQuery = null;
  163. try {
  164. String sql = "select * from " + indexName;
  165. String whereTemp = "";
  166. if (StringUtils.isNotBlank(whereExpress)) {
  167. whereTemp = " where 1=1 " + whereExpress;
  168. }
  169. SQLQueryExpr sqlExpr = (SQLQueryExpr) toSqlExpr(sql + whereTemp);
  170. SqlParser sqlParser = new SqlParser();
  171. MySqlSelectQueryBlock query = (MySqlSelectQueryBlock) sqlExpr.getSubQuery().getQuery();
  172. WhereParser whereParser = new WhereParser(sqlParser, query);
  173. Where where = whereParser.findWhere();
  174. if (where != null) {
  175. boolQuery = QueryMaker.explan(where);
  176. }
  177. } catch (SqlParseException e) {
  178. logger.info("ReadES.createQueryBuilderByExpress-Exception,"+e.getMessage());
  179. e.printStackTrace();
  180. }
  181. return boolQuery;
  182. }
  183. /**
  184. * 构建查询构造器
  185. * @return
  186. */
  187. public BoolQueryBuilder createQueryBuilderBySql(String sql) {
  188. BoolQueryBuilder boolQuery = null;
  189. try {
  190. SQLQueryExpr sqlExpr = (SQLQueryExpr) toSqlExpr(sql);
  191. SqlParser sqlParser = new SqlParser();
  192. MySqlSelectQueryBlock query = (MySqlSelectQueryBlock) sqlExpr.getSubQuery().getQuery();
  193. WhereParser whereParser = new WhereParser(sqlParser, query);
  194. Where where = whereParser.findWhere();
  195. if (where != null) {
  196. boolQuery = QueryMaker.explan(where);
  197. }
  198. } catch (SqlParseException e) {
  199. logger.info("ReadES.createQueryBuilderByExpress-Exception,"+e.getMessage());
  200. e.printStackTrace();
  201. }
  202. return boolQuery;
  203. }
  204. /**
  205. * 验证sql
  206. *
  207. * @param sql sql查询语句
  208. * @return and (a=1 and b=1) or (c=1 and d=1)
  209. */
  210. private SQLExpr toSqlExpr(String sql) {
  211. SQLExprParser parser = new ElasticSqlExprParser(sql);
  212. SQLExpr expr = parser.expr();
  213. if (parser.getLexer().token() != Token.EOF) {
  214. throw new ParserException("illegal sql expr : " + sql);
  215. }
  216. return expr;
  217. }
  218. /**
  219. * 查询指定索引下的信息
  220. * @param indexName 索引名称
  221. * @param condition 查询条件
  222. * queryIndexContent("user_site"," and phone_no in('12234567890') ");
  223. */
  224. public List<Map<String,Object>> queryIndexContent(String indexName, String condition) throws IOException {
  225. //实例化查询请求对象
  226. SearchRequest request = new SearchRequest();
  227. //实例化SearchSourceBuilder
  228. SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
  229. //根据索引、查询条件构建查询构造器
  230. BoolQueryBuilder boolQueryBuilder = createQueryBuilderByWhere(indexName,condition);
  231. //将查询构造器注入SearchSourceBuilder
  232. searchBuilder.query(boolQueryBuilder);
  233. //设置请求查询的索引(查询构造器中已指定,无需重复设置)
  234. //request.indices(indexName);
  235. //将构建好的SearchSourceBuilder注入请求
  236. request.source(searchBuilder);
  237. //带入请求执行查询
  238. SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
  239. //得到查询结果
  240. SearchHits hits = searchResponse.getHits();
  241. SearchHit[] searchHits = hits.getHits();
  242. List<Map<String,Object>> listData = new ArrayList<>();
  243. //遍历查询结果
  244. for(SearchHit hit : searchHits){
  245. Map<String,Object> datas = hit.getSourceAsMap();
  246. listData.add(datas);
  247. logger.info(datas.toString());
  248. }
  249. return listData;
  250. }
  251. /**
  252. * 查询语句转换
  253. * @param filters
  254. * @return
  255. */
  256. public QueryBuilder getQueryBuilder(String filters) {
  257. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  258. if (StringUtils.isEmpty(filters)) {
  259. return boolQueryBuilder;
  260. }
  261. String [] filterArr = filters.split(";");
  262. for (String filter : filterArr) {
  263. if (filter.contains("||")){
  264. String [] fields = filter.split("\\|\\|");
  265. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
  266. for (String filed : fields) {
  267. String [] condition = filed.split("=");
  268. queryBuilder.should(QueryBuilders.termQuery(condition[0], condition[1]));
  269. }
  270. boolQueryBuilder.must(queryBuilder);
  271. } else if (filter.contains("?")) {
  272. String [] condition = filter.split("\\?");
  273. MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery(condition[0], condition[1]);
  274. boolQueryBuilder.must(matchPhraseQueryBuilder);
  275. } else if (filter.contains("<>")) {
  276. String [] condition = filter.split("<>");
  277. if (condition[1].contains(",")) {
  278. String [] inCondition = condition[1].split(",");
  279. TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(condition[0], inCondition);
  280. boolQueryBuilder.mustNot(termsQueryBuilder);
  281. } else {
  282. TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(condition[0], condition[1]);
  283. boolQueryBuilder.mustNot(termQueryBuilder);
  284. }
  285. } else if (filter.contains(">=")) {
  286. String [] condition = filter.split(">=");
  287. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(condition[0]);
  288. rangeQueryBuilder.gte(condition[1]);
  289. boolQueryBuilder.must(rangeQueryBuilder);
  290. } else if (filter.contains(">")) {
  291. String [] condition = filter.split(">");
  292. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(condition[0]);
  293. rangeQueryBuilder.gt(condition[1]);
  294. boolQueryBuilder.must(rangeQueryBuilder);
  295. } else if (filter.contains("<=")) {
  296. String [] condition = filter.split("<=");
  297. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(condition[0]);
  298. rangeQueryBuilder.lte(condition[1]);
  299. boolQueryBuilder.must(rangeQueryBuilder);
  300. } else if (filter.contains("<")) {
  301. String [] condition = filter.split("<");
  302. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(condition[0]);
  303. rangeQueryBuilder.lt(condition[1]);
  304. boolQueryBuilder.must(rangeQueryBuilder);
  305. } else if (filter.contains("=")) {
  306. String [] condition = filter.split("=");
  307. if (condition[1].contains(",")) {
  308. String [] inCondition = condition[1].split(",");
  309. TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(condition[0], inCondition);
  310. boolQueryBuilder.must(termsQueryBuilder);
  311. } else {
  312. TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(condition[0], condition[1]);
  313. boolQueryBuilder.must(termQueryBuilder);
  314. }
  315. }
  316. }
  317. return boolQueryBuilder;
  318. }
  319. /**
  320. * 多条件查询
  321. * @param mustMap
  322. * @param length
  323. * @return
  324. */
  325. public List<String> multiSearch(Map<String,Object> mustMap,int length,String index) {
  326. // 根据多个条件 生成 boolQueryBuilder
  327. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  328. // 循环添加多个条件
  329. for (Map.Entry<String, Object> entry : mustMap.entrySet()) {
  330. boolQueryBuilder.must(QueryBuilders
  331. .matchQuery(entry.getKey(), entry.getValue()));
  332. }
  333. // boolQueryBuilder生效
  334. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  335. searchSourceBuilder.query(boolQueryBuilder);
  336. searchSourceBuilder.size(length);
  337. // 其中listSearchResult是自己编写的方法,以供多中查询方式使用。
  338. return listSearchResult(searchSourceBuilder,index);
  339. }
  340. /**
  341. * 用来处理搜索结果,转换成链表
  342. * @param builder
  343. * @return
  344. */
  345. public List<String> listSearchResult(SearchSourceBuilder builder,String index) {
  346. // 提交查询
  347. SearchRequest searchRequest = new SearchRequest(index);
  348. searchRequest.source(builder);
  349. // 获得response
  350. SearchResponse searchResponse = null;
  351. try {
  352. searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  353. } catch (IOException e) {
  354. e.printStackTrace();
  355. }
  356. // 从response中获得结果
  357. List<String> list = new LinkedList<>();
  358. SearchHits hits = searchResponse.getHits();
  359. Iterator<SearchHit> iterator = hits.iterator();
  360. while(iterator.hasNext()) {
  361. SearchHit next = iterator.next();
  362. list.add(next.getSourceAsString());
  363. }
  364. return list;
  365. }
  366. }