近期有大数据项目需要用到es,而又是比较新的es版本,网上也很少有8.x的java整合教程,所有写下来供各位参考。
首先
1.导包:
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.2.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>8.2.0</version>
</dependency>
2.客户端连接代码EsUtilConfigClint:
一开始按照其他博主的方法,长时间连接不操作查询再次调用查询时会报错timeout,所以要设置RequestConfigCallback
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@Configuration
public class EsUtilConfigClint {
/**
* 客户端
* @return
* @throws IOException
*/
@Bean
public ElasticsearchClient elasticsearchClient(){
RestClient client = RestClient.builder(new HttpHost("127.0.0.1", 9200,"http"))
.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
//设置修改长时间连接项目会报错timeout
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder.setConnectTimeout(90000000)//25hours
.setSocketTimeout(90000000);
}
})
.setHttpClientConfigCallback((httpAsyncClientBuilder -> {
httpAsyncClientBuilder.disableAuthCaching();//禁用身份验证缓存
//显式设置keepAliveStrategy
httpAsyncClientBuilder.setKeepAliveStrategy((httpResponse, httpContext) -> TimeUnit.MINUTES.toMillis(3));
//显式开启tcp keepalive
httpAsyncClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setSoKeepAlive(true).build());
return httpAsyncClientBuilder;
})).build();
ElasticsearchTransport transport = new RestClientTransport(client, new JacksonJsonpMapper());
return new ElasticsearchClient(transport);
}
}
3.增删改查:
数据实体类:
import lombok.Data;
@Data
public class EsMess {
private String id;
private String title;
private String content;
private Date createTime;
}
3.1.索引创建方法:
@Service
public class EsIndexService {
@Resource
private ElasticsearchClient client;
public final static String INDEX_NAME = "test";
/**
* 增加index
* @throws IOException
*/
public boolean create() throws IOException {
CreateIndexResponse indexResponse = client.indices().create(c -> c.index(INDEX_NAME));
System.out.println(indexResponse.toString());
return indexResponse.acknowledged();
}
}
3.2.新增数据:
@Service
public class EsService {
@Resource
private ElasticsearchClient client;
public void add(EsMess esMess) throws IOException {
IndexResponse indexResponse = client.index(i->i.index(EsIndexService.INDEX_NAME).id(esMess.getId()).document(esMess));
}
}
3.3.修改数据:
/**
* 更新Document
* @throws IOException
*/
public void update(EsMess esMess) throws IOException {
UpdateResponse<EsMess> updateResponse = client.update(u -> u
.index(EsIndexService.INDEX_NAME)
.id(esMess.getId())
.doc(esMess)
, EsMess.class);
}
3.4.查询单条记录:
/**
* 查询Document
* @throws IOException
*/
public EsMess get(String id) throws IOException {
GetResponse<EsMess> getResponse = client.get(g -> g
.index(EsIndexService.INDEX_NAME)
.id(id)
, EsMess.class
);
EsMess esMess = getResponse.source();
return esMess;
}
3.5.删除记录:
/**
* 删除Document
* @throws IOException
*/
public void delete(String id) throws IOException {
DeleteResponse deleteResponse = client.delete(d -> d
.index(EsIndexService.INDEX_NAME)
.id(id)
);
}
3.6.批量插入:
/**
* 批量插入Document
* @throws IOException
*/
public void bulk(List<EsMess> esMessList) throws IOException {
List<BulkOperation> bulkOperationArrayList = new ArrayList<>();
for(EsMess esMess : esMessList){
bulkOperationArrayList.add(BulkOperation.of(x->x.create(d->d.document(esMess).id(esMess.getId()).index(EsIndexService.INDEX_NAME))));
}
BulkResponse bulkResponse = client.bulk(b -> b.index(EsIndexService.INDEX_NAME).operations(bulkOperationArrayList));
}
4.复杂查询
4.1.分页多字段查询(1w条数据以内):
/**
* search
* key:查询内容
* page:页数
* limit:每页条数
* @throws IOException
*/
public List<EsMess> search(String key,Integer page,Integer limit) throws IOException {
SearchRequest.Builder builder = new SearchRequest.Builder();
//设置查询索引
builder.index(EsIndexService.INDEX_NAME);
//组装查询条件
BoolQuery.Builder boolQuery = new BoolQuery.Builder();
if(StringUtil.isNotBlank(key)){
boolQuery.should(q -> q.matchPhrasePrefix(m -> m
.query(key)
//字段名
.field("title")
));
//多字段匹配
boolQuery.should(q->q.matchPhrasePrefix(m->m.query(key).field("content")));
}
builder.query(q -> q.bool(boolQuery.build()));
//分页
if(page!=null && limit!=null){
builder.from(page).size(limit);
}
//排序
builder.sort(sortOptionsBuilder -> sortOptionsBuilder
.field(fieldSortBuilder -> fieldSortBuilder
.field("createTime").order(SortOrder.Desc)));
SearchResponse<EsMess> response = client.search(builder.build(), EsMess.class);
List<EsMess> list = new ArrayList<>();
List<Hit<EsMess>> hits = response.hits().hits();
for (Hit<EsMess> hit : hits) {
EsMess esMess = hit.source();
list.add(esMess);
}
return list;
}
4.2.searchafter(1w条数据以后的分页)+高亮查询+时间范围查询等
es中1w条数据以后如果使用form(page).size(limit)会报错Result window is too large, from + size must be less than or equal to: [10000] but was [100001]
有scroll查询或通过配置文件设置最大查询数量也可以解决但是太耗费性能文章来源:https://www.toymoban.com/news/detail-513856.html
所以使用searchafter查询,需要注意的是searchafter查询需要对数据进行排序,查询下一页时需要设置唯一值id的排序,我使用的是id和createTime进行排序文章来源地址https://www.toymoban.com/news/detail-513856.html
/**
* 1w条数据以后的分页
* @param key
* @param page
* @param limit
* @param lastId 上一页最后一条数据唯一id
* @param lastTime 上一页最后一条数据时间
* @return
* @throws IOException
*/
public List<EsMess> searchAfter(String key,Integer page,Integer limit,String lastId,long lastTime) throws IOException {
SearchRequest.Builder builderAfter = new SearchRequest.Builder();
builderAfter.index(EsIndexService.INDEX_NAME);
BoolQuery.Builder boolQuery = new BoolQuery.Builder();
//设置查询条件
if(StringUtil.isNotBlank(key)){
boolQuery.should(q -> q.matchPhrasePrefix(m -> m
.query(key)
.field("title")
));
boolQuery.should(q->q.matchPhrasePrefix(m->m.query(key).field("content")));
}
//时间范围查询 paramMap startTime endTime
//boolQuery.must(q->q.range(r->r.field("createTime").gte(JsonData.of(param.get("startTime"))).lte(JsonData.of(param.get("endTime")))));
builderAfter.query(q -> q.bool(boolQuery.build()));
//设置排序
List<SortOptions> sorts = new ArrayList<>();
SortOptions sortOptions2 = SortOptions.of(s -> s.field(f -> f.field("id.keyword").order(SortOrder.Desc)));
SortOptions sortOptions = SortOptions.of(s -> s.field(f -> f.field("createTime").order(SortOrder.Desc)));
//注意先后顺序
sorts.add(sortOptions);
sorts.add(sortOptions2);
builderAfter.sort(sorts);
builderAfter.size(limit);
//第一页不需要设置,当第二页时需要带排序字段
if(page>0){
builderAfter.searchAfter(
String.valueOf(lastTime),
lastId
);
}
//设置所有字段匹配高亮。注:高亮标签可根据前端需求自定义
if(StringUtil.isNotBlank(key)){
Highlight.Builder highlightBuilder = new Highlight.Builder();
highlightBuilder.fields("*",new HighlightField.Builder().build()).preTags("<span style=\"color:red\">").postTags("</span>").requireFieldMatch(false);
builderAfter.highlight(highlightBuilder.build());
}
//发送查询
SearchResponse response = client.search(builderAfter.build(),EsMess.class);
List<EsMess> list = new ArrayList<>();
List<Hit<EsMess>> hits = response.hits().hits();
for (Hit<EsMess> hit : hits) {
EsMess esMess = hit.source();
//获取高亮数据添加到实体类中返回
Map<String,List<String>> highlightMap = hit.highlight();
if(highlightMap!=null && !highlightMap.isEmpty()){
highlightMap.keySet().forEach(k->{
try {
if(k.contains("keyword")){
k = k.replace(".keyword","");
}
Field field = esMess.getClass().getDeclaredField(k);
field.setAccessible(true);
field.set(esMess,highlightMap.get(k).get(0));
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
list.add(esMess);
}
return list;
}
到了这里,关于java-springboot整合ElasticSearch8.2复杂查询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!