由于目前的项目上其他同事有es搜索应用的需求,但是由于学习成本较高,所以我构思了一个简单的工具类,针对spring boot注入的es进行elasticsearch6.3版本以后推出的sql功能, 把sql转为dsl并返回搜索结果(因为es sql的jdbc是收费的,所以用这种方法可以做到sql搜索)。
直接上代码:(泛型为实体类,用来把es响应结果转对象用的)
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.SearchHit;
import org.springframework.data.elasticsearch.core.EntityMapper;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created by penghao on 2018/9/20.
*/
public class ESSpringBootUtils<T> {
private static EntityMapper entityMapper;
/**
* 该方法主要功能是获取es的查询响应体
* @param client es client对象
* @param dsl 查询语句DSL
* @param indices 索引,可以是多个
* @return
*/
public static SearchResponse responseDsl(Client client, String dsl, String... indices){
SearchResponse response = client.prepareSearch(indices).setSource(dsl).execute().actionGet();
return response;
}
/**
* 该方法主要功能是获取es的查询结果并转成对象
* @param client es client对象
* @param dsl 查询语句DSL
* @param indices 索引,可以是多个
* @return
*/
public List<T> objResultDsl(Client client, String dsl, String... indices){
try {
SearchResponse response = client.prepareSearch(indices).setSource(dsl).execute().actionGet();
SearchHit[] hits = response.getHits().getHits();
ArrayList<T> objResult = new ArrayList<>();
Class <T> entityClass = (Class <T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
for (SearchHit hit:hits){
T t = entityMapper.mapToObject(hit.getSourceAsString(), entityClass);
objResult.add(t);
}
return objResult;
} catch (IOException e) {
e.printStackTrace();
}
return new ArrayList<T>();
}
/**
* sql转DSL(该功能仅用于es6.3以上版本)
* @param ip es服务器的ip地址,只需要任意一个就行
* @param port es端口号,默认9300
* @param sql sql语句
* @param size 返回数量
* @return 转换的DSL语句
*/
public static String esSql2Dsl(String ip, Integer port, String sql, Integer size){
String url = "http://" + ip + ":" + port + "/_xpack/sql/translate";
HashMap<String, Object> jsonMap = new HashMap<>();
if (sql.endsWith(";")){
sql = sql.substring(0, sql.length() - 1);
}
jsonMap.put("query", sql);
if (size != null){
jsonMap.put("fetch_size", sql);
}
String s = "";
try {
s = sendHttpPost(url, jsonMap.toString());
} catch (Exception e) {
e.printStackTrace();
}
return s;
}
/**
* sql转DSL(该功能仅用于es6.3以上版本)
* @param ip es服务器的ip地址,只需要任意一个就行
* @param port es端口号,默认9300
* @param sql sql语句
* @return 转换的DSL语句
*/
public static String esSql2Dsl(String ip, Integer port, String sql){
return esSql2Dsl(ip, port, sql, null);
}
private static String sendHttpPost(String url, String body) throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
httpPost.setEntity(new StringEntity(body));
CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String responseContent = EntityUtils.toString(entity, "UTF-8");
response.close();
httpClient.close();
return responseContent;
}
}
这么做的目的只有一个,就是用免费的方法用最低的学习成本(直接写sql),达到搜索的目的。