Springboot集成elasticsearch有多种方式,如TransportClient、
RestHighLevelClient等等;但是官方已经停止更新TransportClient并且在elasticsearch8.0之后已经弃用,所以本人使用的是RestHighLevelClient。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置文件
elasticsearch:
url: 127.0.0.1
port: 9200
配置类
@Configuration
public class ElasticSearchConfig {
@Value("#{elasticsearch.url}")
private String url;
@Value("#{elasticsearch.port}")
private String port;
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost(url, 9200)));
return client;
}
}
public Boolean createIndex(String indexNam) {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexNam.toLowerCase());
createIndexRequest.settings(Settings.builder().put("index.number_of_shards", 4)
.put("index.number_of_replicas", 2));
try {
XContentBuilder xContentBuilder= XContentFactory.jsonBuilder();
xContentBuilder.startObject().startObject("properties")
.startObject("type").field("type", "integer").endObject()
.startObject("content").field("type", "text").field("analyzer", "ik_max_word").endObject()
.endObject().endObject();
createIndexRequest.mapping(xContentBuilder);
CreateIndexResponse response = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
boolean acknowledged = response.isAcknowledged();
// 指示是否在超时之前为索引中的每个分片启动了必需的分片副本数
boolean shardsAcknowledged = response.isShardsAcknowledged();
if (acknowledged || shardsAcknowledged) {
log.info("创建索引成功!索引名称为{}", indexNam);
return Boolean.TRUE;
}
} catch (IOException e) {
log.info("创建索引失败{}",e);
}
return Boolean.FALSE;
}
创建索引CreateIndexRequest这里只传索引名称,没有类型了,因为elasticsearch7.6 索引将去除type 没有类型的概念了。
elasticsearch有自己的数据类型如下
一、字符串类型
1)text:用于全文索引,搜索时自动使用分词器分词后匹配
2)keyword:不分词,精确匹配
二、数字类型
1)整数类型:integer、long、byte、short
2)浮点类型: float,、half_float、 scaled_float、double
三、日期类型:date
但是如果我们传入的json字符串怎么办?
#插入|更新此字段的值时,有3种表示方式
#使用固定格式的字符串
“2020-04-18”、“2020/04/18 09:00:00”
#值使用长整型的时间戳,1970-01-01 00:00:00,s
1610350870
#值使用长整型的时间戳,ms
1641886870000
四、布尔 boolean
analyzer:ik_max_word 表示会对文本做最细 力度的拆分
analyzer:ik_smart 表示会对文本做最粗粒度的拆分
public Boolean isIndexExists(final String indexName) {
try {
GetIndexRequest request = new GetIndexRequest(indexName.toLowerCase());
return restHighLevelClient.indices().exists(request,RequestOptions.DEFAULT);
} catch (IOException e) {
log.info("查看索引是否存在失败{}",e);
return Boolean.FALSE;
}
}
public Boolean removeIndex(String indexName) {
try {
DeleteIndexRequest deleteIndexRequest=new DeleteIndexRequest(indexName.toLowerCase());
AcknowledgedResponse acknowledgedResponse=restHighLevelClient.indices().delete(deleteIndexRequest,RequestOptions.DEFAULT);
if(acknowledgedResponse.isAcknowledged()){
return Boolean.TRUE;
}
} catch (IOException e) {
log.error("删除索引失败{}",e);
}
return Boolean.FALSE;
}
public Boolean saveDocment(ElasticSearchCommon elasticSearchCommon) {
if(!this.isIndexExists(elasticSearchCommon.getIndexName().toLowerCase())){
this.createIndex(elasticSearchCommon);
}
IndexRequest indexRequest=new IndexRequest(elasticSearchCommon.getIndexName());
indexRequest.id(elasticSearchCommon.getId());
indexRequest.timeout("3s");
indexRequest.source(JSON.toJSONString(elasticSearchCommon), XContentType.JSON);
IndexResponse response = null;
try {
response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
log.info("存储文档失败{}",e);
}
return response.getShardInfo().getSuccessful()>0?true:false;
}
es存储文档的时候不需要创建索引index,可以自动创建index,但是字段类型都是默认的,所以重要的字段一定要自己创建。
public Boolean delDocment(String id, String indexName) {
DeleteRequest deleteRequest=new DeleteRequest();
deleteRequest.timeout("3s");
deleteRequest.id(id);
DeleteResponse deleteResponse = null;
try {
deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
log.info("删除文档失败{}",e);
}
return deleteResponse.getShardInfo().getSuccessful()>0?true:false;
}
public PageResult<ElasticSearchResponseBean> searchIndex(final ElasticSearchRequestBean elasticSearchRequestBean) {
SearchRequest searchRequest = new SearchRequest(elasticSearchRequestBean.getIndexName());
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from((elasticSearchRequestBean.getPage().getPageNum()-1)*elasticSearchRequestBean.getPage().getPageSize());
searchSourceBuilder.size(elasticSearchRequestBean.getPage().getPageSize());
searchSourceBuilder.trackTotalHits(true);//用于显示正确的总数
BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
if(StringUtils.isNotEmpty(elasticSearchRequestBean.getKeyWord())){
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("content", elasticSearchRequestBean.getKeyWord());
boolQueryBuilder.must(fuzzyQueryBuilder);
}
if(elasticSearchRequestBean.getType()!=null){
TermQueryBuilder termQueryBuilder=QueryBuilders.termQuery("type",elasticSearchRequestBean.getType());
boolQueryBuilder.must(termQueryBuilder);
}
searchSourceBuilder.query(boolQueryBuilder);
searchSourceBuilder.timeout(new TimeValue(3, TimeUnit.SECONDS));
searchRequest.source(searchSourceBuilder);
PageResult<ElasticSearchResponseBean> pageResult=new PageResult<>();
List<ElasticSearchResponseBean> list=new ArrayList<>();
Long total=0L;
try {
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
if (search.getHits().getHits().length!=0){
Map<Object,Object> map=null;
for (SearchHit documentFields : search.getHits().getHits()) {
map=new HashMap<>();
map.putAll(documentFields.getSourceAsMap());
list.add(BeanUtil.mapToObj(map,ElasticSearchResponseBean.class));
}
total=search.getHits().getTotalHits().value;
}
pageResult.setRecord(list);
pageResult.setTotalCount(total);
pageResult.setCurrentPage(elasticSearchRequestBean.getPage().getPageNum());
pageResult.setPageSize(elasticSearchRequestBean.getPage().getPageSize());
pageResult.setPageCount(total/elasticSearchRequestBean.getPage().getPageSize());
return pageResult;
} catch (IOException e) {
log.info("搜索失败{}",e);
}
return pageResult;
}
elasticsearch搜索条件比较多,简单是说几个
BoolQueryBuilder:多条件查询器
TermQueryBuilder:单条件查询器
FuzzyQueryBuilder :模糊查询器
所有的查询器都要通过searchSourceBuilder进行查询;
想要什么的查询器可以去QueryBuilders类中查看;
如果项目中搜索不是基于算分进行排序的,可以搜索的时候取消算分功能加快查询效率
1、自定义排序规则不会算分
2、无评分查询器,ConstantScoreQueryBuilder
MatchQueryBuilder matchQueryBuilder= QueryBuilders.matchQuery("content", keyWord);
ConstantScoreQueryBuilder constantScoreQueryBuilder=QueryBuilders.constantScoreQuery(matchQueryBuilder);
searchSourceBuilder.query(constantScoreQueryBuilder);