说明:
由于elastic 更新较快,这里只介绍spring boot 集成的elastic7.17.4 ,如果想直接使用elastic8,推荐你再搜搜别的
本文章大概可以坚持到2024年(如果更新会往后推)
没有2.7版本可以试着升一下spring boot2升级至2.7.3环境配置
RestHighLevelClient 已弃用
ElasticsearchRepository已弃用
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
<version>2.7.3version>
dependency>
注意了,当前版本就是这个,原来的版本要注意会存在多字段
spring:
elasticsearch:
uris: 192.168.2.91:9200
#username:
#password:
#connection-timeout: 1
#read-timeout: 30 默认30
需要注意大小写以及下划线转换
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
/**
* @author king
*/
@Data
@Document(indexName = "my_user")
public class MyUser {
@Id
private String id;
private String username;
private String password;
private String realname;
private String nickname;
private String file;
// 这里没用到
public MyUser(String id, String username, String password,String realname, String nickname, String file) {
this.id = id;
this.username = username;
this.password = password;
this.realname = realname;
this.nickname = nickname;
this.file = file;
}
public MyUser() {
}
}
这里贴一个我自己写的util,可以直接用在service里
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Collection;
/**
* @author king
* 2022-08-23
* 此方法适用于 spring boot 2.7.X 以及spring boot 当前版本集成下的elastic-7.17.4
* 涵盖sprng-data-elasticsearch-4.4.2
*/
@Component
public class ElasticUtils {
@Resource
ElasticsearchRestTemplate elasticsearchRestTemplate;
/**
* 新增索引(表)
*/
public <T> Boolean put(T entity) {
IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
return indexOperations.create();
}
/**
* 判断索引是否存在
*/
public <T> Boolean exists(T entity) {
IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
return indexOperations.exists();
}
/**
* 删除索引
*/
public <T> Boolean delete(T entity) {
IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
return indexOperations.delete();
}
/**
* 修整索引字段(与实体类保持一致,一般为增加,减少字段未测试)
*/
public <T> Boolean mapping(T entity) {
IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(entity.getClass());
return indexOperations.putMapping();
}
/**
* 插入
*/
public <T> T save(T entity) {
return elasticsearchRestTemplate.save(entity);
}
/**
* 批量插入
*/
public Iterable saveBatch(Collection collectors) {
return elasticsearchRestTemplate.save(collectors);
}
/**
* 根据主键查询
*/
public <T> Object get(String id, T entity) {
return elasticsearchRestTemplate.get(id, entity.getClass());
}
/**
* 根据主键删除
*/
public <T> String delete(String id, T entity) {
return elasticsearchRestTemplate.delete(id, entity.getClass());
}
/**
* 多条件查询
*/
public <T> SearchHits<?> search(T entity, NativeSearchQueryBuilder queryBuilder) {
IndexCoordinates indexCoordinatesFor = elasticsearchRestTemplate.getIndexCoordinatesFor(entity.getClass());
return elasticsearchRestTemplate.search(queryBuilder.build(), entity.getClass(), indexCoordinatesFor);
}
}
这里先介绍三个query
TermQueryBuilder 精确匹配,MatchPhraseQueryBuilder 模糊匹配,BoolQueryBuilder布尔查询,布尔查询可以嵌套 前边两个条件
// 精确匹配,对中文不友好(仅一个字符),没有分词器概念,查询条件为一个字符时可以多重匹配,多个字符类似于mysql 的等于条件
//TermQueryBuilder
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("username", "wangw");
// 模糊匹配,存在分词器概念,可将查询条件分成多个字符进行查询
//MatchPhraseQueryBuilder
MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("realname", "张");
// 布尔查询,可以将上述的各种条件添加入bool中作为多条件查询
BoolQueryBuilder
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 必须条件 and
boolQueryBuilder.must(termQueryBuilder);
// 只要满足即可 or
boolQueryBuilder.should(termQueryBuilder);
这里贴一个查询实例:
public void test() {
MatchPhraseQueryBuilder termQueryBuilder = QueryBuilders.matchPhraseQuery("nickname", "可恶");
MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("realname", "张");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(termQueryBuilder);
boolQueryBuilder.should(termQueryBuilder);
// 查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.withSourceFilter(new FetchSourceFilterBuilder().build())
// 高亮
.withHighlightFields(
new HighlightBuilder.Field("nickname"),
new HighlightBuilder.Field("realname")
)
// 去除查询结果 只取聚合查询的结果
// 分页
.withFields()
.withPageable(PageRequest.of(0, 10));
IndexCoordinates indexCoordinatesFor = elasticsearchRestTemplate.getIndexCoordinatesFor(MyUser.class);
SearchHits<MyUser> search = elasticsearchRestTemplate.search(queryBuilder.build(), MyUser.class, indexCoordinatesFor);
List<SearchHit<MyUser>> searchHits = search.getSearchHits();
List<MyUser> posts = new ArrayList<>();
//遍历返回的内容进行处理
for(SearchHit<MyUser> searchHit:searchHits){
//高亮的内容
Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
//将高亮的内容填充到content中
searchHit.getContent().setNickname(highlightFields.get("nickname")==null ? searchHit.getContent().getNickname():highlightFields.get("nickname").get(0));
searchHit.getContent().setRealname(highlightFields.get("realname")==null ? searchHit.getContent().getRealname():highlightFields.get("realname").get(0));
//放到实体类中
posts.add(searchHit.getContent());
}
System.out.println(posts);
}