本文介绍:本文介绍ES 7.7 (ElasticSearch) 版本与springboot集成使用,包含多种条件查询,同时将命令行操作展示。若有表述错误地方欢迎指出;
理论知识某度上太多,就不过多解释。
ES 以及kibana 下载可直接通过官网下载:https://www.elastic.co/cn/downloads/elasticsearch
一、命令行操作 (kibana)
1.1、 新增操作
1.1.1 、命令行新增2条数据(不含子类)
命令行新增两条数据 , 启动 customer为索引名称, "_doc"后 数字为id;
请注意 索引名称只支持小写, 索引id有大小写区分
PUT /customer/_doc/1
{
"id":"1",
"name": "xiaoxiao",
"age":28,
"date":"2020-07-07 20:00:01",
"address": "广东深圳福田"
}
PUT /customer/_doc/2
{
"id":"2",
"name": "xiaoAoJiangHu",
"age":31,
"date":"2020-07-07 20:00:01",
"address": "广东深圳福田"
}
1.1.2 、命令行新增两条数据(有子类)
如下所示 cuostomer_detail 为索引名称, a 和A 为ES id , 此处为了便于区分。将实体类id设置和索引id 不一致。实体类id分别为 a1 和A1
PUT /cuostomer_detail/_doc/a
{
"id":"a1",
"name":"xiao_xiao",
"address":"广东深圳福田",
"age":18,
"demoList":[
{
"id":"s1",
"name":"小张的大儿子"
},
{
"id":"S2",
"name":"小张的小儿子"
}
],
"listStr":[
"str1",
"str2"
]
}
PUT /cuostomer_detail/_doc/A
{
"id":"A1",
"name":"小张",
"address":"广东深圳福田翰林院",
"age":18,
"demoList":[
{
"id":"D1",
"name":"小张的哥哥"
},
{
"id":"s1",
"name":"小张的大儿子"
}
],
"listStr":[
"str1",
"str2"
]
}
1.1.2 、新增数据和修改数据返回说明。 kibana put之后如果id在当前索引不存在则是新增 直接返回成功,若是ES索引id已经存在,则修改,如下分别为新增和修改的返回数据
新增返回说明: _index--索引名称
_type -- 索引类型
_id -- 索引ID
_version -- 版本号,修改了多少次
result 表示创建或者修改
_shards -- 分片信息
{
"_index" : "cuostomer_detail",
"_type" : "_doc",
"_id" : "a12",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 4,
"_primary_term" : 1
}
修改返回: result 和新增不一致
{
"_index" : "cuostomer_detail",
"_type" : "_doc",
"_id" : "A",
"_version" : 3,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 5,
"_primary_term" : 1
}
1.2、 查询操作
1.2.1、 指定id 查询
查询语句, 查询索引名称为 cuostomer_detail 索引id 为A的数据
GET /cuostomer_detail/_doc/A
1.2.2 、 指定ID返回结果 _source 就是实际数据信息
{
"_index" : "cuostomer_detail",
"_type" : "_doc",
"_id" : "A",
"_version" : 3,
"_seq_no" : 5,
"_primary_term" : 1,
"found" : true,
"_source" : {
"id" : "A1",
"name" : "小张",
"address" : "广东深圳福田翰林院",
"age" : 24,
"demoList" : [
{
"id" : "D1",
"name" : "小张的哥哥"
},
{
"id" : "s1",
"name" : "小张的大儿子"
}
],
"listStr" : [
"str1",
"str2"
]
}
}
1.2.3、 多条件查询, 分词查询数据信息,并且按照年龄排序, 从第1条开始查询,总共查询3条
查找地址 “广福东田”的数据 (此处由于有IK分词,没有找到完全匹配的,查询出相似的)
GET /cuostomer_detail/_search
{
"query":{
"match":{
"address":"广福东田"
}
},
"sort":[
{
"age":"asc"
}
],
"from":0,
"size":3
}
返回结果
说明: 第一个 “hits” 表示命中信息
{
"took" : 880,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "cuostomer_detail",
"_type" : "_doc",
"_id" : "A",
"_score" : null,
"_source" : {
"id" : "A1",
"name" : "小张",
"address" : "广东深圳福田翰林院",
"age" : 18,
"demoList" : [
{
"id" : "D1",
"name" : "小张的哥哥"
},
{
"id" : "s1",
"name" : "小张的大儿子"
}
],
"listStr" : [
"str1",
"str2"
]
},
"sort" : [
18
]
},
{
"_index" : "cuostomer_detail",
"_type" : "_doc",
"_id" : "a",
"_score" : null,
"_source" : {
"id" : "a1",
"name" : "xiao_xiao",
"address" : "广东深圳福田",
"age" : 24,
"demoList" : [
{
"id" : "s1",
"name" : "小张的大儿子"
},
{
"id" : "S2",
"name" : "小张的小儿子"
}
],
"listStr" : [
"str1",
"str2"
]
},
"sort" : [
24
]
}
]
}
}
1.2.4、 多条件查询,必须和非必须 (由于篇幅有限,后面数据都不在列举返回结果)
查找 age 为 18 且 name 不等于 “xiao”的
GET /cuostomer_detail/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "18" } }
],
"must_not": [
{ "match": { "name": "xiao" } }
]
}
}
}
1.2.5、 多条件查询,必须(查询子类)和非必须 ,并且包含模糊查询
GET /cuostomer_detail/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"demoList.id":"D1"
}
}
],
"must_not":[
{
"match":{
"name":"xiao"
}
}
],
"should": [
{
"match": {
"name": "张"
}
}
]
}
}
}
二、Java代码集成使用
2.0 、springboot集成ES 需要引入全部jar包信息如下
1.8
UTF-8
7.7.0
1.2.70
org.springframework.boot
spring-boot-starter
org.projectlombok
lombok
true
org.elasticsearch.client
elasticsearch-rest-high-level-client
${elasticsearch.version}
org.elasticsearch.client
elasticsearch-rest-high-level-client
${elasticsearch.version}
org.elasticsearch
elasticsearch
${elasticsearch.version}
org.elasticsearch.client
elasticsearch-rest-client
${elasticsearch.version}
org.springframework.boot
spring-boot-starter-web
com.alibaba
fastjson
${fastjson.version}
2.1 创建链接 链接ES ,此处提供了ES有用户密码的链接方式
此处创建的是高级搜索,如果高级搜索满足不了要求,也可以使用低级搜索。
/**
* 获取高级链接
*
* @return
*/
private RestHighLevelClient getHighClient() {
// getHost() 为获取链接集群的地址
HttpHost[] host = getHost(); // getHost() -- ["http://127.0.0.1:9200"]
RestClientBuilder builder = RestClient.builder(host);
// 设置ES 链接密码
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(esProperties.getUserName(), esProperties.getPassword()));
builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider));
// 创建高级搜索链接,请注意改链接使用完成后必须关闭,否则使用一段时间之后将会抛出异常
RestHighLevelClient restClient = new RestHighLevelClient(builder);
return restClient;
}
2.2 、使用通用接收数据类便于进行批量新增。请注意,批量新增索引的大小在 1000-5000条数据为最佳,数据量大小在 5MB-10MB 为最佳;超过可能会影响性能。
@Data
public class EsBatchAddReq {
/**
* 业务系统编码
*/
@NotBlank(message = "系统编码不能为空")
private String systemCode;
/**
* 业务编码,类似表名
*/
@NotBlank(message = "业务编码不能为空")
private String businessCode;
@Valid
@NotEmpty(message = "插入的数据不能为空")
private List beanList;
/**
* 此处生成的是ES的索引名称,请注意此处没有检验系统编码和业务编码大小写,只能是小写字母,也可以在此处设置转换为小写字母
* @return
*/
public String getEsCode() {
return new StringBuilder(systemCode).append("_").append(businessCode).toString();
}
}
2.3 、批量新增索引, 批量新增的类和获取链接的类请参考上
具体说明已经在下面代码上
public EsResponse upsetIndex(EsBatchAddReq requestParam) throws IOException {
// 获取链接
RestHighLevelClient highClient = getHighClient();
BulkRequest request = new BulkRequest();
// 设置索引名称,索引名称由系统编码和业务编码组成。若业务比较简单,也可以仅设置为一个字段。此处是为了方便多系统多业务使用
request.routing(requestParam.getEsCode());
for (Object o : requestParam.getBeanList()) {
JSONObject jsonObject = (JSONObject) JSON.toJSON(o);
String id = jsonObject.getString(EsConstant.ES_ID);
Assert.notNull(id, "实体类必须包含id");
// 将数据转换为String类型,批量插入时设置为JSON格式
String data = JSONObject.toJSONString(o);
// 实体类必须包含ES自定义主键,搜索引擎ES将根据自定义ID进行重复新验证。
request.add(new IndexRequest(requestParam.getEsCode()).id(id).source(data, XContentType.JSON));
}
// 批量新增数据
BulkResponse bulk = highClient.bulk(request, RequestOptions.DEFAULT);
// TODO 此处缺少是否新增成功判断。可以自行增加
RestStatus status = bulk.status();
// 关闭链接
highClient.close();
return EsResponse.successRes(status.toString());
}
2.4、ES 搜索通用请求类
系统编码和业务编码确定索引使用
fieldsList 表示需要模糊搜索的String类型字段(日期格式推荐使用format转换之后进行搜索),
numberFieldsList 表示数字类型的字段,为了避免搜索类型错误,支持整数搜索
其他各类型map 的key值表示字段名称,value根据场景不同数量可能是1-N个,参加下方代码注释
public class EsSearchReq {
/**
* 业务系统编码
*/
@NotBlank(message = "系统编码不能为空")
private String systemCode;
/**
* 业务编码,类似表名
*/
@NotBlank(message = "业务编码不能为空")
private String businessCode;
/**
* 第几页
*/
private Integer page = 1;
/**
* 每页展示的梳理
*/
private Integer size = 10;
/**
* 从第几条开始(不传)
*/
private Integer from;
/**
* 搜索值
*/
private String searchValue;
/**
* 搜索字段列表,此处的字段类型必须为String类型 或者 date类型且在上面加上 @JSONField(format="yyyy-MM-dd HH:mm:ss") 才行
*/
private List fieldsList;
/**
* 搜索的数字列表
*/
private List numberFieldsList;
/**
* 必须相等
*/
private Map mustMap;
/**
* 必须不等
*/
private Map mustNotMap;
/**
* in条件字符串查询, 字段属性值必须为字符串类型
*/
private Map containMap;
/**
* not in条件字符串查询, 字段属性值必须为字符串类型
* key 是字段名称,
*/
private Map notContainMap;
/**
* 数字in条件查询, 请注意,value必须能转换为数字
*/
private Map numberContainMap;
/**
* 数字not in条件查询.请注意,value必须能转换为数字
*/
private Map numberNotContainMap;
/**
* 在....之间
* key 是字段名称, list只能且必须是两个相同的值
*/
private Map> betweenMap;
/**
* 排序字段列表信息
*/
private List sortFields;
/**
* 是否高亮
*/
private boolean highlight = false;
/**
* 模糊搜索
*/
private Map shouldMap;
/**
* 针对时间、数字类型字段处理 可以和 shouldMap 合并
*/
private Map matchMap;
public Integer getFrom() {
if (from == null) {
from = (page - 1) * size;
}
return from;
}
2.5、ES 的具体执行搜索的代码--重点,包含 (相等、不等、in条件、not in 条件,范围、高亮)等功能
查询相等
查询不等
in 条件查询
not in 条件查询
范围查询
高亮查询
不分词查询使用MatchPhraseQueryBuilder ,如果要分词查询使用MatchQueryBuilder
public EsResponse query(EsSearchReq searchReq) throws IOException {
RestHighLevelClient highClient = getHighClient();
// 拼接索引 设置索引名称
SearchRequest searchRequest = new SearchRequest(searchReq.getEsCode());
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
BoolQueryBuilder shouldBuilder = new BoolQueryBuilder();
if (!CollectionUtils.isEmpty(searchReq.getShouldMap())) {
Map shouldMap = searchReq.getShouldMap();
for (String key : shouldMap.keySet()) {
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder(key, shouldMap.get(key));
shouldBuilder.should(matchQueryBuilder );
}
}
List fieldsList = searchReq.getFieldsList();
String searchValue = searchReq.getSearchValue();
// 排除空格问题
if (null != searchValue && !StringUtils.isEmpty(searchValue.trim()) && !CollectionUtils.isEmpty(fieldsList)) {
List list = fieldsList;
for (String field : list) {
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder(field, searchValue);
// 如果不需要分词,则直接使用下面一行代码替换上面这行代码
// MatchPhraseQueryBuilder matchQueryBuilder = new MatchPhraseQueryBuilder(field, searchValue);
shouldBuilder.should(matchQueryBuilder );
}
}
// 如果搜索的内容为数字 搜索字段列表包含数字字段信息, 此处工具类见下面附录
if (CommonUtil.isInteger(searchValue) && !CollectionUtils.isEmpty(searchReq.getNumberFieldsList())){
Integer searchNumber = Integer.valueOf(searchValue.trim());
for (String field : searchReq.getNumberFieldsList()) {
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder(field, searchNumber);
shouldBuilder.should(matchQueryBuilder );
}
}
boolQueryBuilder.must(shouldBuilder);
/**
* 必须相等
*/
if (!CollectionUtils.isEmpty(searchReq.getMustMap())) {
Map mustMap = searchReq.getMustMap();
for (String field : mustMap.keySet()) {
boolQueryBuilder.must(QueryBuilders.termQuery(field, mustMap.get(field)));
}
}
/**
* 必须不等
*/
if (!CollectionUtils.isEmpty(searchReq.getMustNotMap())) {
Map mustNotMap = searchReq.getMustNotMap();
for (String field : mustNotMap.keySet()) {
boolQueryBuilder.mustNot(QueryBuilders.termQuery(field, mustNotMap.get(field)));
}
}
/**
* in 条件查询 查询的字段属性必须为字符串类型才可以
*/
if (!CollectionUtils.isEmpty(searchReq.getContainMap())) {
Map containMap = searchReq.getContainMap();
for (String field : containMap.keySet()) {
Object[] objects = containMap.get(field);
Assert.notNull(objects, "containMap 中的值不能为空");
String searchKey = new StringBuilder(field).append(".keyword").toString();
boolQueryBuilder.must(QueryBuilders.termsQuery(searchKey, objects));
}
}
/**
* not in 条件查询 查询的字段属性必须为字符串类型才可以
*/
if (!CollectionUtils.isEmpty(searchReq.getNotContainMap())) {
Map notInMap = searchReq.getNotContainMap();
for (String field : notInMap.keySet()) {
Object[] objects = notInMap.get(field);
Assert.notNull(objects, "notInMap 中的值不能为空");
String searchKey = new StringBuilder(field).append(".keyword").toString();
boolQueryBuilder.mustNot(QueryBuilders.termsQuery(searchKey, objects));
}
}
boolQueryBuilder.must(containBuilder);
/**
* in 条件查询 查询的字段属性必须为数字类型才可以
*/
if (!CollectionUtils.isEmpty(searchReq.getNumberContainMap())) {
Map numberContainMap = searchReq.getNumberContainMap();
for (String field : numberContainMap.keySet()) {
Long[] objects = numberContainMap.get(field);
Assert.notNull(objects, "numberContainMap 中的值不能为空");
boolQueryBuilder.must(QueryBuilders.termsQuery(field, objects));
}
}
/**
* not in 条件查询 查询的字段属性必须为数字类型才可以
*/
if (!CollectionUtils.isEmpty(searchReq.getNumberNotContainMap())) {
Map numberNotContainMap = searchReq.getNumberNotContainMap();
for (String field : numberNotContainMap.keySet()) {
Long[] objects = numberNotContainMap.get(field);
Assert.notNull(objects, "numberNotContainMap 中的值不能为空");
boolQueryBuilder.mustNot(QueryBuilders.termsQuery(field, objects));
}
}
/**
* 范围查询
*/
if (!CollectionUtils.isEmpty(searchReq.getBetweenMap())) {
Map> betweenMap = searchReq.getBetweenMap();
for (String field : betweenMap.keySet()) {
List objects = betweenMap.get(field);
Assert.notNull(objects, "betweenMap 中的值不能为空");
Assert.isTrue(objects.size() == 2, "betweenMap的值大小必须为2");
RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder(field).gte(objects.get(0)).lte(objects.get(1));
boolQueryBuilder.must(rangeQueryBuilder);
}
}
/**
* 高亮展示 后续方案可以考虑设置类型或者
*/
/*if (searchReq.getHighlight() && !CollectionUtils.isEmpty(searchReq.getHighLights())) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
searchReq.getHighLights().forEach(a -> {
HighlightBuilder.Field field = new HighlightBuilder.Field(a);
// 此处是设置高亮类型 后续扩展
// highlightTitle.highlighterType("unified");
highlightBuilder.field(field);
});
sourceBuilder.highlighter(highlightBuilder);
}*/
/**
* 排序功能
*/
if (!CollectionUtils.isEmpty(searchReq.getSortFields())) {
sourceBuilder.sort(new FieldSortBuilder("_score").order(SortOrder.DESC));
searchReq.getSortFields().forEach(a -> {
SortOrder sortOrder = a.isAsc() ? SortOrder.ASC : SortOrder.DESC;
sourceBuilder.sort(new FieldSortBuilder(a.getColumn()).order(sortOrder));
});
}
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.from(searchReq.getFrom());
sourceBuilder.size(searchReq.getSize());
searchRequest.source(sourceBuilder);
SearchResponse search = highClient.search(searchRequest, RequestOptions.DEFAULT);
highClient.close();
log.info("ES查询返回的初始信息为:{}", JSONObject.toJSONString(search));
EsResponse pageResponse = EsResponseUtil.getPageResponse(search, searchReq.getPage(), searchReq.getSize());
log.info("ES查询返回的结果信息转换后的数据信息为:{}", JSONObject.toJSONString(pageResponse));
return pageResponse;
}
三、附录 ,其他工具类信息
3.1 、判断是否为数字
public class CommonUtil{
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
String trim = str.trim();
if (trim == null || trim.length() > 8) {
return false;
}
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(trim).matches();
}
}
3.2 、反射获取类String类型、Date类型字段列表,如果是子类,则按需求拼接 (父字段名.子字段名);获取数字字段列表
public class EsBeanUtil {
private final static String SERIAL_VERSION_UID = "serialVersionUID";
private final static String STRING_VALUE = "java.lang.String";
private final static String DATE_VALUE = "java.util.Date";
private final static String INTEGER_VALUE = "java.lang.Integer";
private final static String SHORT_VALUE = "java.lang.Short";
private final static String LONG_VALUE = "java.lang.Long";
private final static String BIGDECIMAL_VALUE = "java.math.BigDecimal";
/**
* 获取类的所有字段信息
*
* @param clazz
* @param prefix 前缀
* @return
*/
public static Map getStringFieldsMap(String prefix, Class clazz) {
Field[] declaredFields = clazz.getDeclaredFields();
Map map = new HashMap<>();
String prefixNam = StringUtils.isEmpty(prefix) ? "" : prefix + ".";
for (Field field : declaredFields) {
if (SERIAL_VERSION_UID.equals(field.getName())) {
continue;
}
if (STRING_VALUE.equals(field.getType().getName())) {
map.put(prefixNam + field.getName(), field.getName());
} else if (DATE_VALUE.equals(field.getType().getName())) {
// 日期类型 判断是否有字段
JSONField annotation = field.getAnnotation(JSONField.class);
if (annotation != null) {
map.put(prefixNam + field.getName(), field.getName());
}
}
}
return map;
}
public final static Map numberMap() {
Map numberMap = new HashMap<>(16);
numberMap.put("java.lang.Double", "1");
numberMap.put("java.lang.Integer", "1");
numberMap.put("java.lang.Long", "1");
numberMap.put("int", "1");
numberMap.put("long", "1");
numberMap.put("double", "1");
numberMap.put("java.math.BigDecimal", "1");
return numberMap;
}
/**
* 获取类的所有字段信息
*
* @param clazz
* @return
*/
public static List getStringFieldsList(String prefix, Class clazz) {
Field[] declaredFields = clazz.getDeclaredFields();
List fields = new ArrayList<>();
String prefixNam = StringUtils.isEmpty(prefix) ? "" : prefix + ".";
Map numberMap = numberMap();
for (Field field : declaredFields) {
if (SERIAL_VERSION_UID.equals(field.getName())) {
continue;
}
// 如果是日期类型 则判断是否有做处理 否则不做处理
if (DATE_VALUE.equals(field.getType().getName())) {
// 日期类型 判断是否有字段
JSONField annotation = field.getAnnotation(JSONField.class);
if (annotation != null) {
fields.add(prefixNam + field.getName());
}
// 排除数字类型数据
} else if (!numberMap.containsKey(field.getType().getName())) {
fields.add(prefixNam + field.getName());
}
}
return fields;
}
/**
* 获取类的所有字段信息
*
* @param clazz
* @return
*/
public static List getNumberFieldsList(String prefix, Class clazz) {
Field[] declaredFields = clazz.getDeclaredFields();
List fields = new ArrayList<>();
String prefixNam = StringUtils.isEmpty(prefix) ? "" : prefix + ".";
Map map = numberMap();
for (Field field : declaredFields) {
if (SERIAL_VERSION_UID.equals(field.getName())) {
continue;
}
if (map.containsKey(field.getType().getName())) {
fields.add(prefixNam + field.getName());
}
}
return fields;
}
}
3.3、 EsResponse 类
public class EsResponse implements Serializable {
private static final long serialVersionUID = 14284224234985L;
/**
* 返回编码 0代表成功
*/
private String code = "0";
/**
* 返回参数信息
*/
private String message = "操作成功";
/**
* 是否成功
*/
private Boolean success = true;
/**
* 数据信息
*/
private String data;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public static EsResponse successRes() {
return new EsResponse();
}
public static EsResponse successRes(String data) {
EsResponse response = new EsResponse();
response.setData(data);
return response;
}
public static EsResponse failRes() {
EsResponse response = new EsResponse();
response.setSuccess(Boolean.FALSE);
response.setCode("999999");
response.setMessage("ES操作错误,请联系管理员");
return response;
}
public static EsResponse failRes(String retMsg) {
EsResponse response = new EsResponse();
response.setSuccess(Boolean.FALSE);
response.setCode("999999");
response.setMessage(retMsg);
return response;
}
public static EsResponse failRes(String retCode, String retMsg) {
EsResponse response = new EsResponse();
response.setSuccess(Boolean.FALSE);
response.setCode(retCode);
response.setMessage(retMsg);
return response;
}
}
EsResponseUtil 工具类
package com.lxzl.es.util;
import com.alibaba.fastjson.JSONObject;
import com.es.common.entity.EsPage;
import com.es.common.entity.EsResponse;
import org.apache.http.HttpStatus;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author: xiaoxiao
* @Date: 2020/7/16 9:48
* @Desc: Es 处理请求工具类
*/
public class EsResponseUtil {
public static EsResponse getPageResponse(SearchResponse response, int page, int size){
EsResponse esResponse;
List resultList = new ArrayList<>(size * 2);
// 如果成功
if (HttpStatus.SC_OK == response.status().getStatus()) {
esResponse = new EsResponse();
SearchHits searchHits = response.getHits();
Long hitsTotal = searchHits.getTotalHits().value;
EsPage esPage = new EsPage(page, size, hitsTotal);
SearchHit[] hits = response.getHits().getHits();
if (hits != null && hits.length != 0) {
for (SearchHit searchHit : hits) {
Map sourceAsMap = searchHit.getSourceAsMap();
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(sourceAsMap));
resultList.add(jsonObject);
}
}
esPage.setList(resultList);
esResponse.setData(JSONObject.toJSONString(esPage));
} else {
esResponse = EsResponse.failRes(String.valueOf(response.status().getStatus()), response.status().toString());
}
return esResponse;
}
}
EsProperties 配置类
@Component
@ConfigurationProperties(prefix = "skull.es")
@Data
public class EsProperties {
/**
* ES 的服务地址信息
*/
private String[] ip_address = {"127.0.0.1:9200"};
/**
* 链接超时时间配置,默认1秒
*/
private Long connectTimeout = 1000L;
/**
* 通话超时时间 默认 30秒
*/
private Long socketTimeout = 300000L;
/**
* 访问身份认证, 设置在请求头中,和appKeySecret组合使用
*/
private String appKeyId = "";
/**
* 访问身份认证,设置在请求头中, 和appKeyId组合使用
*/
private String appKeySecret = "";
/**
* 设置批量请求的数量 bulkActions
*/
private Integer bulkActions = 1000;
/**
* 设置批量请求的大小,和 byteSizeType组合使用, 默认5M
*/
private Long byteSizeValue = 5L;
/**
* 设置批量请求大小的衡量单位,可选 BYTES, KB, MB, GB, TB, PB
*/
private String byteSizeType = "MB";
/**
* 设置并发请求的数量。默认是1, 0表示仅运行执行单个请求
*/
private Integer concurrentRequests = 1;
/**
* 设置刷新时间,默认10秒
*/
private Long flushInterval = 10L;
/**
* 设置重试机制时间间隔(秒), 默认1秒重试3次,和 backoffPolicyNumber 重试次数组合使用
*/
private Long backoffPolicySeconds = 1L;
/**
* 设置重试机制的次数,默认1秒重试3次,和 backoffPolicySeconds 组合使用
*/
private Integer backoffPolicyNumber = 3;
private String userName = "";
private String password = "";
}
EsConstant 常量类
public class EsConstant {
/**
* 系统编码和业务编码下唯一标识
*/
public static final String ES_ID = "id";
public static final String HTTP_STR = "http";
}
以上所有是目前暂时实现的。若有其他可以留言互相探讨