第一步:引入依赖co.elastic.clients elasticsearch-java 8.1.2 jakarta.json jakarta.json-api
第二步:配置文件 elasticsearch: rest: host: localhost port: 9200 scheme: http read-timeout: 20 userName: root password: root
第三步:读取配置文件 加ES保活策略
/** * @Author D_TZ * @Date 2022/11/314:16 * @ClassName ElashConfig * @Desription **/ @Configuration public class ElasticSearchConfig { @Value("${elasticsearch.rest.host}") private String host; @Value("${elasticsearch.rest.scheme}") private String scheme; @Value("${elasticsearch.rest.port}") private int port; @Value("${elasticsearch.rest.userName}") private String userName; @Value("${elasticsearch.rest.password}") private String password; @Bean public ElasticsearchClient elasticsearchClient(){ ElasticsearchClient client = new ElasticsearchClient(null); final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); //设置账号密码 credentialsProvider.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials(userName, password)); RestClient restClient = RestClient.builder(new HttpHost(host, port,scheme)) // 异步httpclient配置 .setHttpClientConfigCallback( httpClientBuilder -> { // 账号密码登录 httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); // httpclient保活策略 httpClientBuilder.setKeepAliveStrategy(((response, context) -> Duration.ofMinutes(5).toMillis())); return httpClientBuilder; }).build(); ElasticsearchTransport transport = new RestClientTransport(restClient,new JacksonJsonpMapper()); // And create the API client client = new ElasticsearchClient(transport); return client; }
第四步使用:注入 ElasticsearchClient 只截取主要代码部分
@Autowired private ElasticsearchClient client;
/** * 首页成果查询 * * @param dto * @return * @Author D_TZ */ @Override public AjaxResult esSearch(EsSearchDto dto) { //检查参数 if (dto == null || StringUtils.isBlank(dto.getKeyword())) { return AjaxResult.error("缺少搜索参数"); }
SearchResponse
try { search = client.search(s -> s .index(dto.getIndexName()) .query(q1 -> q1 // bool 条件查询 .bool(b1 -> b1 // 与 使用构建器lambda将值添加到must。 .must(m1 -> m1 .bool(b2 -> b2 // or 条件查询 .should(s1 -> s1 .match(m2 -> m2 .field("title") .query(dto.getKeyword()))) .should(s1 -> s1 .wildcard(w2 -> w2 .field("title") .wildcard("*" + dto.getKeyword() + "*"))) .should(s2 -> s2 .match(m3 -> m3 .field("content") .query(dto.getKeyword()))) .should(s2 -> s2 .wildcard(w3 -> w3 .field("content") .wildcard("*" + dto.getKeyword() + "*"))) )) )) // 分页条件 .from(dto.getFromIndex()) .size(dto.getPageSize()) // 高亮查询 .highlight(h -> h .fields("title", highlightContentBuilder -> highlightContentBuilder.type("plain")) .fields("content", highlightContentBuilder -> highlightContentBuilder.type("plain")) .preTags(preTags) .postTags(postTags) .requireFieldMatch(false) // .encoder(HighlighterEncoder.Html) ), SzpdCgSearchVo.class); } catch (IOException e) { e.printStackTrace(); }
基本介绍:ES 8以上均采用流式方法
ES client客户端查找返回结果为你自定义的集合对象接收:
client.search() 查询类
.index 要查找的索引库
.query 查询条件
.bool 布尔拼接查询条件
.must 一定匹配
.highlight 高亮查询
.field 查找的目标字段
.should 类似OR 条件查询
.match 在match查询的时候也会对查询条件进行分词,然后通过倒排索引找到匹配的数据。在match中支持以下参数
all 返回所有文档,相当于执行了match_all
.wildcard 拼接查询通配符
preTags 将一个或多个值添加到预标签。
postTags
.from(dto.getFromIndex()) 当前页
.size(dto.getPageSize()) 每页条数
第四步:添加文档到索引库 删除,更新等操作。
@Autowired private ElasticsearchClient client; /** * 保存到成果索引库 * * @param Vo对象 * @author Thd */ @Override public void addOrUpdateToEsIndex(ObjectVo vo ) { try { IndexResponse indexResponse = client.index(i -> i.index(vo .getIndexName()).id(vo.getId() + vo.getBusinessType()) .document(vo)); log.info("ES新增成功" + indexResponse.index()); } catch (IOException e) { e.printStackTrace(); log.error("sync es error={}",e); } }
/** * 更新索引库 * * @param szpdCgSearchVo */ @Override public void updateCgToEsIndex(ObjectVo vo) { try { UpdateResponseupdateResponse = client.update(u -> u .index(vo .getIndexName()) .id(vo.getId() + vo.getBusinessType()) .doc(vo) , ObjectVo.class); log.info("新增索引库成功 + {}" + updateResponse.index()); } catch (IOException e) { log.info("Async exception {}" + e); e.printStackTrace(); } }
/** * @param id 逐个删除ES-id * @param businessType 业务类型 * @author Thd */ @Override public void publicDeleteCgToEsIndex(Long id, String businessType , String indexName) { try { DeleteResponse deleteResponse = client.delete(d -> d .index(indexName) .id(id + businessType)); log.info("删除Es数据成功" + deleteResponse.index()); } catch (IOException e) { log.info("Async exception {}" + e); e.printStackTrace(); } }
查询Dto对象;
/** * @Author D_TZ * @Date 2022/9/2018:07 * @ClassName EsSearchDto * @Desription **/ @Data public class EsSearchDto { /** * 搜索关键字 */ private String keyword; /** * 搜索索引库名 */ private String indexName; /** * 当前页 */ private Integer pageNum; /** * 每页条数 */ private Integer pageSize; public int getFromIndex(){ if(this.pageNum<1)return 0; if(this.pageSize<1) this.pageSize = 50; return this.pageSize * (pageNum-1); } }
我这里演示比较简单:业务类型根据自己需求而定
正常考虑系统健壮性来说:在往索引库添加内容的时候最好通过消息队列来添加。删除也一样。