M
Spring data Elasticsearch 配置使用
Spring data Elasticsearch 配置使用
Elasticsearch:7.6.2
spring cloud: Hoxton.SR5
1 安装es
Docker 安装es & es-head & kibana & 中文分词 & 拼音分词
2 maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
3 配置文件
spring:
data:
elasticsearch:
# ip 加端口的形式
cluster-nodes: xxx.xxx.xxx.xxx:9300
cluster-name: elasticsearch
elasticsearch:
rest:
# 健康检查地址 如果用的远端的es的话,需要加这个,不然默认走127.0.0.1:9200 进行健康检查
uris: ["xxx.xxx.xxx.xxx:9200"]
4 实体(索引)
@Data
@Document(indexName = "article", type = "segment")
public class NCArticleSegment {
// es主键
private String id;
// es 相似度
private Float score;
// 文章主键
@Field(type = FieldType.Keyword)
private Long articleId;
// 标题
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title;
// 段落文本
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String segmentTxt;
}
indexName
索引名称
type
类型 7.0.0以后将将不建议使用,8.0.0 以后完全不支持
FieldType
text
- 支持分词,全文检索,支持模糊、精确查询,不支持聚合,排序操作;
- 最大支持的字符长度无限制,适合大字段存储;
使用场景:
存储全文搜索数据, 例如: 邮箱内容、地址、代码块、博客文章内容等。
默认结合standard analyzer(标准解析器)对文本进行分词、倒排索引。默认结合标准分析器进行词命中、词频相关度打分。
keyword
- 不进行分词,直接索引,支持模糊、支持精确匹配,支持聚合、排序操作。
- keyword类型的最大支持的长度为——32766个UTF-8类型的字符,可以通过设置ignore_above指定自持字符长度,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。
使用场景:
存储邮箱号码、url、name、title,手机号码、主机名、状态码、邮政编码、标签、年龄、性别等数据。
用于筛选数据(例如: select * from x where status=‘open’)、排序、聚合(统计)。
直接将完整的文本保存到倒排索引中。
5 Dao
@Repository
public interface NCArticleSegmentDao extends ElasticsearchRepository<NCArticleSegment, String> {
}
6 Service
@Service
public class ArticleSegmentServiceImpl implements ArticleSegmentService {
@Autowired
NCArticleSegmentDao segmentDao;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Override
public void addSegment(NCArticleSegment segment) {
segment.setCreateTime(new Date());
segmentDao.save(segment);
}
public List<NCArticleSegment> getSegmentList2(QueryVO<NCArticleSegment> queryVO) {
QueryBuilder queryBuilder = QueryBuilders.matchQuery("segmentTxt", queryVO.getData().getSegmentTxt());
Iterable<NCArticleSegment> iterable = segmentDao.search(queryBuilder);
return IterableUtils.toList(iterable);
}
@Override
public List<NCArticleSegment> getSegmentList(QueryVO<NCArticleSegment> queryVO) {
//创建一个要搜索的索引库
SearchRequestBuilder searchRequestBuilder = elasticsearchTemplate.getClient().prepareSearch("article").setTypes("segment");
//创建组合查询
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
if (queryVO.getData().getSegmentTxt() != null) {
boolQueryBuilder.must(QueryBuilders.matchQuery("segmentTxt", queryVO.getData().getSegmentTxt()));
}
//设置查询的类型
searchRequestBuilder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH);
searchRequestBuilder.setQuery(boolQueryBuilder);
//分页
searchRequestBuilder.setFrom((queryVO.getPageNum() - 1) * queryVO.getPageSize());
searchRequestBuilder.setSize(queryVO.getPageSize());
//设置高亮字段
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("segmentTxt")
.preTags("<font color='red'>")
.postTags("</font>");
searchRequestBuilder.highlighter(highlightBuilder);
//直接搜索返回响应数据 (json)
SearchResponse searchResponse = searchRequestBuilder.get();
SearchHits hits = searchResponse.getHits();
//获取总条数
long totalHits = hits.getTotalHits();
ArrayList<NCArticleSegment> list = new ArrayList<>();
//获取Hits中json对象数据
SearchHit[] hitList = hits.getHits();
for (int i = 0; i < hitList.length; i++) {
//获取Map对象
Map<String, Object> sourceAsMap = hitList[i].getSourceAsMap();
//获取高亮字段
Map<String, HighlightField> highlightFields = hitList[i].getHighlightFields();
//!!如果有高亮字段就取出赋给上面sourceAsMap中原有的名字给他替换掉!!
if (queryVO.getData().getSegmentTxt() != null) {
sourceAsMap.put("segmentTxt",highlightFields.get("segmentTxt").getFragments()[0].toString());
}
NCArticleSegment segment = new NCArticleSegment();
segment.setId(hitList[i].getId());
segment.setScore(hitList[i].getScore());
if (sourceAsMap.get("articleId") != null) {
segment.setArticleId(Long.valueOf(String.valueOf(sourceAsMap.get("articleId"))));
}
if (sourceAsMap.get("title") != null) {
segment.setTitle(String.valueOf(sourceAsMap.get("title")));
}
if (sourceAsMap.get("segmentTxt") != null) {
segment.setSegmentTxt(String.valueOf(sourceAsMap.get("segmentTxt")));
}
list.add(segment);
}
return list;
}
@Override
public void createSegmentIndex() {
// 创建索引,会根据NCArticleSegment类的@Document注解信息来创建
elasticsearchTemplate.createIndex(NCArticleSegment.class);
// 配置映射,会根据NCArticleSegment类中的id、Field等字段来自动完成映射
elasticsearchTemplate.putMapping(NCArticleSegment.class);
}
}
NCArticleSegmentDao
和 ElasticsearchTemplate
NCArticleSegmentDao
:适合于添加,简单查询,更多功能后期摸索到了在补充ElasticsearchTemplate
:适合于复杂查询,文本高亮等
createIndex
和putMapping
用于在es中创建索引和配置字段规则,不使用这种方法的话使用es接口也可以进行配置
Kibana Dev Tools
# 创建索引
PUT article
{
"settings": {
"index":{
"analysis":{
"analyzer": "ik_max_word"
}
}
}
}
# 配置映射
POST article/_mapping
{
"article" : {
"mappings" : {
"properties" : {
"articleId" : {
"type" : "keyword"
},
"segmentTxt" : {
"type" : "text",
"analyzer" : "ik_max_word"
}
"title" : {
"type" : "text",
"analyzer" : "ik_max_word"
}
}
}
}
}