环境配置:SpringBoot:2.6.0 ,Elasticsearch:7.16.2
1、pom配置
<properties>
<elasticsearch.version>7.16.2</elasticsearch.version>
</properties>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<!-- ES 版本 -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.plugin/transport-netty4-client -->
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
2、yaml配置
#elasticsearch 多个地址逗号隔开
elasticsearch:
hostlist: ${eshostlist:10.1.13.235:9200}
ips: 10.1.13.235
port: 9300
pool: 30
cluster: elasticsearch
3、配置config,获取springBean工具类见下文SpringContextUtils
import com.test.util.SpringContextUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.bulk.*;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.core.TimeValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Iterator;
import java.util.function.BiConsumer;
/**
* @Author bug
* @create 2022/05/6 19:43
* @Description
*/
@Configuration
@Slf4j
public class ESConfig {
@Value("${elasticsearch.hostlist}")
private String hostlist;
/**
* Description: 高版本客户端
*
* @Author: bug
* @Date: 2022/05/15 10:20
* @Return: org.elasticsearch.client.RestHighLevelClient
* @throws:
*/
@Bean("restHighLevelClient")
public RestHighLevelClient restHighLevelClient() {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// 解析 hostlist 配置信息。假如以后有多个,则需要用 , 分开
String[] split = hostlist.split(",");
// 创建 HttpHost 数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for (int i = 0; i < split.length; i++) {
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
// 创建RestHighLevelClient客户端
return new RestHighLevelClient(RestClient.builder(httpHostArray));
}
/**
* Description: 项目主要使用 RestHighLevelClient,对于低级的客户端暂时不用
*
* @Author: bug
* @Date: 2022/05/15 10:20
* @Return: org.elasticsearch.client.RestClient
* @throws:
*/
@Bean
public RestClient restClient() {
// 解析hostlist配置信息
String[] split = hostlist.split(",");
// 创建HttpHost数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for (int i = 0; i < split.length; i++) {
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
return RestClient.builder(httpHostArray).build();
}
public static RestHighLevelClient getRestHighLevelClient() {
RestHighLevelClient restHighLevelClient = null;
try {
restHighLevelClient = (RestHighLevelClient) SpringContextUtils.getBeanListOfType(RestHighLevelClient.class).get(0);
} catch (Exception e) {
log.error("获取restHighLevelClient失败:" + e.toString());
}
return restHighLevelClient;
}
/**
* Description: 封装 bulkProcessor
*
* @Author: bug
* @Date: 2022/05/15 10:19
* @Return: org.elasticsearch.action.bulk.BulkProcessor
* @throws:
*/
@Bean(name = "bulkProcessor")
public BulkProcessor bulkProcessor() {
BiConsumer<BulkRequest, ActionListener<BulkResponse>> bulkConsumer =
(request, bulkListener) -> getRestHighLevelClient().bulkAsync(request, RequestOptions.DEFAULT, bulkListener);
return BulkProcessor.builder(bulkConsumer, new BulkProcessor.Listener() {
@Override
public void beforeBulk(long executionId, BulkRequest request) {
// todo do something
int i = request.numberOfActions();
log.info("ES 同步数量 Executing bulk [{}] with {} requests",
executionId, i);
}
@Override
public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
if (response.hasFailures()) {
log.error("Bulk [{}] executed with failures", executionId);
} else {
log.info("Bulk [{}] completed in {} milliseconds",
executionId, response.getTook().getMillis());
}
// todo do something
Iterator<BulkItemResponse> iterator = response.iterator();
while (iterator.hasNext()) {
log.info("afterBulk--->>>" + JSON.toJSONString(iterator.next()));
}
}
@Override
public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
// todo do something
log.error("ES 同步失败 Failed to execute bulk", failure);
}
//达到刷新的条数,达到刷新的大小,固定刷新的时间频率,并发线程数,重试补偿策略
}).setBulkActions(1000)
.setBulkSize(new ByteSizeValue(1, ByteSizeUnit.MB))
.setFlushInterval(TimeValue.timeValueMinutes(5))
.setConcurrentRequests(2)
.setBackoffPolicy(BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))
.build();
}
}
4、工具类SpringContextUtils.java
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author bug
* @create 2022/05/6 16:12
* @Description 获取srpingBean
*/
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static <T> List<T> getBeanListOfType(Class<T> clazz) {
List<T> result = new ArrayList<>();
Map<String, T> map = applicationContext.getBeansOfType(clazz);
if (null != map) {
result.addAll(map.values());
}
return result;
}
public static <T> List<T> getBeanListOfName(String className) throws Exception {
Class clazz = Class.forName(className);
return getBeanListOfType(clazz);
}
public static void autowireBean(Object bean) {
applicationContext.getAutowireCapableBeanFactory().autowireBean(bean);
}
public static <T> T getBean(String name,Class<T> clazz){
return applicationContext.getBean(name, clazz);
}
}
5、工具类ElasticsearchUtil.java
import com.test.model.domain.EsPage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.util.UUID;
/**
* @Author bug
* @create 2022/05/7 13:45
* @Description ES工具类 该工具类适用于7.*已上版本
* 最好不要自定义id 会影响插入速度
*/
@Component
@Slf4j
public class ElasticsearchUtil {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient restHighLevelClient;
@Autowired
@Qualifier("bulkProcessor")
private BulkProcessor bulkProcessor;
/**
* 关键字 .keyword
*/
public static final String KEYWORD = ".keyword";
/**
* 关键字 *
*/
public static final String WILD_CODE_A = "*";
/**
* 关键字 ?
*/
public static final String WILD_CODE_B = "?";
/**
* 创建索引
*
* @param index
* @return
*/
public boolean createIndex(String index) throws IOException {
if (isIndexExist(index)) {
log.error("Index is exits!");
return false;
}
//1.创建索引请求
CreateIndexRequest request = new CreateIndexRequest(index);
//2.执行客户端请求
org.elasticsearch.client.indices.CreateIndexResponse response = restHighLevelClient.indices()
.create(request, RequestOptions.DEFAULT);
return response.isAcknowledged();
}
/**
* 判断索引是否存在
*
* @param index
* @return
*/
public boolean isIndexExist(String index) throws IOException {
GetIndexRequest request = new GetIndexRequest(index);
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
return exists;
}
/**
* 删除索引
*
* @param index
* @return
*/
public boolean deleteIndex(String index) throws IOException {
if (!isIndexExist(index)) {
log.error("Index is not exits!");
return false;
}
DeleteIndexRequest request = new DeleteIndexRequest(index);
AcknowledgedResponse delete = restHighLevelClient.indices()
.delete(request, RequestOptions.DEFAULT);
return delete.isAcknowledged();
}
/**
* 数据添加,自定义id
*
* @param object 要增加的数据
* @param index 索引,类似数据库
* @param type 类似数据表
* @param id 数据ID,为null时es随机生成
* @return
*/
public String addData(Object object, String index, String type, String id) throws Exception {
//创建请求
IndexRequest request = new IndexRequest(index, type);
//规则 put /test_index/_doc/1
(id);
//将数据放入请求 json
IndexRequest source = request.source(JacksonMapperUtils.obj2json(object), XContentType.JSON);
//客户端发送请求
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
return response.getId();
}
/**
* 数据添加 随机id 可能存在性能问题
*
* @param object 要增加的数据
* @param index 索引,类似数据库
* @param type 类似数据表
* @return
*/
public String addData(Object object, String index, String type) throws Exception {
return addData(object, index, type, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
}
/**
* 通过ID删除数据
*
* @param index 索引,类似数据库
* @param type 类似数据表
* @param id 数据ID
* @return
*/
public void deleteDataById(String index, String type, String id) throws IOException {
DeleteRequest request = new DeleteRequest(index, type, id);
restHighLevelClient.delete(request, RequestOptions.DEFAULT);
}
/**
* 通过ID 更新数据
*
* @param object 要更新数据
* @param index 索引,类似数据库
* @param type 类似数据表
* @param id 数据ID
* @return
*/
public void updateDataById(Object object, String index, String type, String id) throws Exception {
log.info("es更新--->>>esId:" + id);
UpdateRequest update = new UpdateRequest(index, type, id);
update.doc(JacksonMapperUtils.obj2json(object), XContentType.JSON);
restHighLevelClient.update(update, RequestOptions.DEFAULT);
log.info("es更新返回--->>>esId:" + id);
}
/**
* 通过ID 更新数据
*
* @param object 要更新数据
* @param index 索引,类似数据库
* @param type 类似数据表
* @param id 数据ID
* @return
*/
public void updateDocById(Map<String, Object> object, String index, String type, String id) throws Exception {
log.info("es更新--->>>esId:" + id);
UpdateRequest update = new UpdateRequest(index, type, id).doc(object);
update.doc(JacksonMapperUtils.obj2json(object), XContentType.JSON);
restHighLevelClient.update(update, RequestOptions.DEFAULT);
log.info("es更新返回--->>>esId:" + id);
}
/**
* Description: 批量更新
*
* @param: list
* @param: index
* @param: type
* @param: keyId
* @Author: 123107
* @Date: 2022/05/15 10:34
* @Return: void
* @throws:
*/
public void bulkUpdate(List<?> list, String index, String type, String keyId) throws Exception {
log.info("es bulk 更新--->>>start");
for(Object object : list){
String json = JacksonMapperUtils.obj2json(object);
Map<String, Object> map = JacksonMapperUtils.json2map(JacksonMapperUtils.obj2json(object));
String id = String.valueOf(map.get(keyId));
UpdateRequest update = new UpdateRequest(index, id).doc(json, XContentType.JSON);
update.doc(json, XContentType.JSON);
bulkProcessor.add(update);
}
log.info("es bulk 更新--->>end");
}
/**
* 通过ID获取数据
*
* @param index 索引,类似数据库
* @param type 类似数据表
* @param id 数据ID
* @param fields 需要显示的字段,逗号分隔(缺省为全部字段)
* @return
*/
public Map<String, Object> searchDataById(String index, String type, String id, String fields) throws IOException {
GetRequest request = new GetRequest(index, type, id);
if (StringUtils.isNotEmpty(fields)) {
//只查询特定字段。如果需要查询所有字段则不设置该项。
request.fetchSourceContext(new FetchSourceContext(true, fields.split(","), Strings.EMPTY_ARRAY));
}
GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
return response.getSource();
}
/**
* 通过ID判断文档是否存在
*
* @param index 索引,类似数据库
* @param type 类似数据表
* @param id 数据ID
* @return
*/
public boolean existsById(String index, String type, String id) throws IOException {
GetRequest request = new GetRequest(index, type, id);
//不获取返回的_source的上下文
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
return restHighLevelClient.exists(request, RequestOptions.DEFAULT);
}
/**
* 批量插入false成功
*
* @param index 索引,类似数据库
* @param type 类似数据表
* @param objects 数据
* @return
*/
public boolean bulkPost(String index, String type, List<?> objects) throws Exception{
BulkRequest bulkRequest = new BulkRequest();
BulkResponse response = null;
//最大数量不得超过20万
for (Object object : objects) {
IndexRequest request = new IndexRequest(index, type);
request.source(JacksonMapperUtils.obj2json(object), XContentType.JSON);
bulkRequest.add(request);
}
try {
response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
return response.hasFailures();
}
/**
* 根据经纬度查询范围查找location 经纬度字段,distance 距离中心范围KM,lat lon 圆心经纬度
*
* @param index
* @param longitude
* @param latitude
* @param distance
* @return
*/
public SearchResponse geoDistanceQuery(String index, Float longitude, Float latitude, String distance) throws IOException {
if (longitude == null || latitude == null) {
return null;
}
//拼接条件
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//QueryBuilder isdeleteBuilder = QueryBuilders.termQuery("isdelete", false);
// 以某点为中心,搜索指定范围
GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder("location");
distanceQueryBuilder.point(latitude, longitude);
//查询单位:km
distanceQueryBuilder.distance(distance, DistanceUnit.KILOMETERS);
boolQueryBuilder.filter(distanceQueryBuilder);
//boolQueryBuilder.must(isdeleteBuilder);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(boolQueryBuilder);
SearchRequest searchRequest = new SearchRequest(index);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
return searchResponse;
}
/**
* 获取低水平客户端
*
* @return
*/
public RestClient getLowLevelClient() {
return restHighLevelClient.getLowLevelClient();
}
/**
* 高亮结果集 特殊处理
* map转对象 JSONObject.parseObject(JSONObject.toJSONString(map), Content.class)
*
* @param searchResponse
* @param highlightField
*/
private List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
//解析结果
ArrayList<Map<String, Object>> list = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
Map<String, HighlightField> high = hit.getHighlightFields();
HighlightField title = high.get(highlightField);
Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
//解析高亮字段,将原来的字段换为高亮字段
if (title != null) {
Text[] texts = title.fragments();
String nTitle = "";
for (Text text : texts) {
nTitle += text;
}
//替换
sourceAsMap.put(highlightField, nTitle);
}
list.add(sourceAsMap);
}
return list;
}
/**
* 查询并分页
* 单个匹配termQuery
* //不分词查询 参数1: 字段名,参数2:字段查询值,因为不分词,所以汉字只能查询一个字,英语是一个单词.
* QueryBuilder queryBuilder=QueryBuilders.termQuery("fieldName", "fieldlValue");
* //分词查询,采用默认的分词器
* QueryBuilder queryBuilder2 = QueryBuilders.matchQuery("fieldName", "fieldlValue");
* 多个匹配
* //不分词查询,参数1: 字段名,参数2:多个字段查询值,因为不分词,所以汉字只能查询一个字,英语是一个单词.
* QueryBuilder queryBuilder=QueryBuilders.termsQuery("fieldName", "fieldlValue1","fieldlValue2...");
* //分词查询,采用默认的分词器
* QueryBuilder queryBuilder= QueryBuilders.multiMatchQuery("fieldlValue", "fieldName1", "fieldName2", "fieldName3");
* //匹配所有文件,相当于就没有设置查询条件
* QueryBuilder queryBuilder=QueryBuilders.matchAllQuery();
* <p>
* 模糊查询常见的5个方法如下
* //1.常用的字符串查询-左右模糊
* QueryBuilders.queryStringQuery("fieldValue").field("fieldName");
* //2.常用的用于推荐相似内容的查询-如果不指定filedName,则默认全部,常用在相似内容的推荐上
* QueryBuilders.moreLikeThisQuery(new String[] {"fieldName"}).addLikeText("pipeidhua");
* //3.前缀查询 如果字段没分词,就匹配整个字段前缀
* QueryBuilders.prefixQuery("fieldName","fieldValue");
* //4.fuzzy query:分词模糊查询,通过增加fuzziness模糊属性来查询,如能够匹配hotelName为tel前或后加一个字母的文档,fuzziness 的含义是检索的term 前后增加或减少n个单词的匹配查询
* QueryBuilders.fuzzyQuery("hotelName", "tel").fuzziness(Fuzziness.ONE);
* //5.wildcard query:通配符查询,支持* 任意字符串;?任意一个字符
* //前面是fieldname,后面是带匹配字符的字符串
* QueryBuilders.wildcardQuery("fieldName","ctr*");
* QueryBuilders.wildcardQuery("fieldName","c?r?");
* <p>
* 范围查询
* //闭区间查询
* QueryBuilder queryBuilder0 = QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2");
* //开区间查询 默认是true,也就是包含
* QueryBuilder queryBuilder1 = QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2").includeUpper(false).includeLower(false);
* //大于
* QueryBuilder queryBuilder2 = QueryBuilders.rangeQuery("fieldName").gt("fieldValue");
* //大于等于
* QueryBuilder queryBuilder3 = QueryBuilders.rangeQuery("fieldName").gte("fieldValue");
* //小于
* QueryBuilder queryBuilder4 = QueryBuilders.rangeQuery("fieldName").lt("fieldValue");
* //小于等于
* QueryBuilder queryBuilder5 = QueryBuilders.rangeQuery("fieldName").lte("fieldValue");
* <p>
* 合查询/多条件查询/布尔查询
* QueryBuilders.boolQuery()
* //文档必须完全匹配条件,相当于and
* QueryBuilders.boolQuery().must();
* //文档必须不匹配条件,相当于not
* QueryBuilders.boolQuery().mustNot();
* //至少满足一个条件,这个文档就符合should,相当于or
* QueryBuilders.boolQuery().should();
*
* @param index 索引名称
* @param type 类似数据表
* @param query 查询条件
* @param size 文档大小限制
* @param startPage 第几页开始 默认0开始
* @param fields 需要显示的字段,逗号分隔(缺省为全部字段)
* @param sortField 排序字段
* @param highlightField 高亮字段
* @return
*/
public EsPage searchListData(String index,
String type,
SearchSourceBuilder query,
Integer size,
Integer startPage,
String fields,
String sortField,
String highlightField) throws IOException {
SearchRequest request = new SearchRequest(index);
//request.types(type);
SearchSourceBuilder builder = query;
if (StringUtils.isNotEmpty(fields)) {
//只查询特定字段。如果需要查询所有字段则不设置该项。
builder.fetchSource(new FetchSourceContext(true, fields.split(","), Strings.EMPTY_ARRAY));
}
startPage = startPage <= 0 ? 0 : startPage * size;
//设置确定结果要从哪个索引开始搜索的from选项,默认为0
builder.from(startPage);
builder.size(size);
if (StringUtils.isNotEmpty(sortField)) {
//排序字段,注意如果proposal_no是text类型会默认带有keyword性质,需要拼接.keyword
builder.sort(sortField + ".keyword", SortOrder.ASC);
}
//高亮
if (StringUtils.isNotEmpty(highlightField)) {
HighlightBuilder highlight = new HighlightBuilder();
highlight.field(highlightField);
//关闭多个高亮
highlight.requireFieldMatch(false);
highlight.preTags("<span style='color:red'>");
highlight.postTags("</span>");
builder.highlighter(highlight);
}
//不返回源数据。只有条数之类的数据。
//builder.fetchSource(false);
request.source(builder);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
long totalHits = response.getHits().getTotalHits().value;
log.info("totalHits==" + response.getHits().getTotalHits());
if (response.status().getStatus() == 200) {
// 解析对象
List<Map<String, Object>> sourceList = setSearchResponse(response, highlightField);
return new EsPage(startPage, size, (int) totalHits, sourceList);
}
return null;
}
/**
* Description: 组装模糊查询参数
*
* @param: filds 模糊查询列
* @param: querys 模糊查询内容
* @param: mustFilds 必须匹配列
* @param: mustQuerys 必须匹配内容
* @Author: 123107
* @Date: 2022/05/14 15:25
* @Return: org.elasticsearch.index.query.BoolQueryBuilder
* @throws:
*/
public BoolQueryBuilder boolQueryBuilder(String filds, String querys, String mustFilds, String mustQuerys) {
if (StringUtils.isBlank(filds) || StringUtils.isBlank(querys)) {
return null;
}
String[] fildList = filds.split(",");
String[] queryList = querys.split(",");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for (String fild : fildList) {
for (String query : queryList) {
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(fild + KEYWORD, WILD_CODE_A + query + WILD_CODE_A);
boolQueryBuilder.should(wildcardQueryBuilder);
}
}
boolQueryBuilder.minimumShouldMatch(1);
//必须匹配条件
if (StringUtils.isNotBlank(mustFilds) && StringUtils.isNotBlank(mustQuerys)) {
String[] mfilds = mustFilds.split(",");
String[] mquserys = mustQuerys.split(",");
if (mfilds.length == mquserys.length) {
for (int i = 0; i < mfilds.length; i++) {
QueryBuilder queryBuilder = QueryBuilders.termQuery(mfilds[i], mquserys[i]);
boolQueryBuilder.must(queryBuilder);
}
}
}
return boolQueryBuilder;
}
}
6、EsPage类
import java.util.Map;
import java.util.List;
/**
* @Author bug
* @create 2022/05/7 9:31
* @Description
*/
public class EsPage {
/**
* 当前页
*/
private int currentPage;
/**
* 每页显示多少条
*/
private int pageSize;
/**
* 总记录数
*/
private int recordCount;
/**
* 本页的数据列表
*/
private List<Map<String, Object>> recordList;
/**
* 总页数
*/
private int pageCount;
/**
* 页码列表的开始索引(包含)
*/
private int beginPageIndex;
/**
* 页码列表的结束索引(包含)
*/
private int endPageIndex;
/**
* 只接受前4个必要的属性,会自动的计算出其他3个属性的值
*
* @param currentPage
* @param pageSize
* @param recordCount
* @param recordList
*/
public EsPage(int currentPage, int pageSize, int recordCount, List<Map<String, Object>> recordList) {
this.currentPage = currentPage;
this.pageSize = pageSize;
this.recordCount = recordCount;
this.recordList = recordList;
// 计算总页码
pageCount = (recordCount + pageSize - 1) / pageSize;
// 计算 beginPageIndex 和 endPageIndex
// >> 总页数不多于10页,则全部显示
if (pageCount <= 10) {
beginPageIndex = 1;
endPageIndex = pageCount;
}
// >> 总页数多于10页,则显示当前页附近的共10个页码
else {
// 当前页附近的共10个页码(前4个 + 当前页 + 后5个)
beginPageIndex = currentPage - 4;
endPageIndex = currentPage + 5;
// 当前面的页码不足4个时,则显示前10个页码
if (beginPageIndex < 1) {
beginPageIndex = 1;
endPageIndex = 10;
}
// 当后面的页码不足5个时,则显示后10个页码
if (endPageIndex > pageCount) {
endPageIndex = pageCount;
beginPageIndex = pageCount - 10 + 1;
}
}
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getRecordCount() {
return recordCount;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public List<Map<String, Object>> getRecordList() {
return recordList;
}
public void setRecordList(List<Map<String, Object>> recordList) {
this.recordList = recordList;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getBeginPageIndex() {
return beginPageIndex;
}
public void setBeginPageIndex(int beginPageIndex) {
this.beginPageIndex = beginPageIndex;
}
public int getEndPageIndex() {
return endPageIndex;
}
public void setEndPageIndex(int endPageIndex) {
this.endPageIndex = endPageIndex;
}
}
7、使用示例
/**
* Description: es 保存数据 //ES_INDEX 索引名称//ES_TYPE type
* @param: obj 数据对象
* @param: id ES_id UUID.randomUUID().toString().replaceAll("-", "").toUpperCase()
* @Author: bug
* @Date: 2022/05/7 18:48
* @Return: java.lang.String
* @throws:
*/
public String insertEs(Object obj, String id) throws Exception {
try {
boolean exists = elasticsearchUtil.isIndexExist(EsIndexConstant.ES_INDEX);
log.info(EsIndexConstant.ES_INDEX + ":index--->>>" + exists);
if (!exists) {
boolean create = elasticsearchUtil.createIndex(EsIndexConstant.ES_INDEX);
log.info(EsIndexConstant.ES_INDEX + ":create--->>>" + create);
}
elasticsearchUtil.addData(obj, EsIndexConstant.ES_INDEX, EsIndexConstant.ES_TYPE, id);
log.info(EsIndexConstant.ES_INDEX + ":es保存返回id--->>>" + id);
return id;
} catch (Exception e) {
log.error("es保存异常:" + e.toString());
throw e;
}
}
/**
* Description: es 更新数据 //ES_INDEX 索引名称//ES_TYPE type
* @param: obj 数据对象
* @param: esNumber ES_id
* @Author: bug
* @Date: 2022/05/7 18:48
* @Return: java.lang.String
* @throws:
*/
public void updateEs(Object obj, String esNumber) throws Exception {
try {
boolean exists = elasticsearchUtil.isIndexExist(EsIndexConstant.ES_INDEX);
log.info(EsIndexConstant.ES_INDEX + ":index--->>>" + exists);
if (!exists) {
boolean create = elasticsearchUtil.createIndex(EsIndexConstant.ES_INDEX);
log.info(EsIndexConstant.ES_INDEX + ":create--->>>" + create);
}
elasticsearchUtil.updateDataById(obj, EsIndexConstant.ES_INDEX, EsIndexConstant.ES_TYPE, esNumber);
log.info(EsIndexConstant.ES_INDEX + ":es编辑返回id--->>>" + esNumber);
} catch (Exception e) {
log.error("es更新异常:" + e.toString());
throw e;
}
}
/**
* Description: es 查询数据 从指定的txt字段中,查询含有words内容的数据//ES_INDEX 索引名称//ES_TYPE type
* @param: words 要查询的内容
* @param: esNumber ES_id
* @Author: bug
* @Date: 2022/05/7 18:48
* @Return: java.lang.List
* @throws:
*/
public List<Map<String, Object>> searchDataFromField(String words)
int currentPage=0;
int pageSize=10000;
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = elasticsearchUtil.boolQueryBuilder("txt", words, null, null);
//增加筛选条件 userType ==1
//BoolQueryBuilder boolQueryBuilder = elasticsearchUtil.boolQueryBuilder("txt", words, "userType","1");
searchSourceBuilder.query(boolQueryBuilder);
EsPage esPage = null;
//要返回的数据字段
String fields = "esId,systemId,systemName,fileName,createTime";
try {
esPage = elasticsearchUtil.searchListData(EsIndexConstant.ES_INDEX, EsIndexConstant.ES_TYPE searchSourceBuilder, pageSize, currentPage, fields, null, null);
} catch (IOException e) {
e.printStackTrace();
}
List<Map<String, Object>> records = esPage.getRecordList();
return records;
}
















