- 1 摘要
- 2 核心 Maven 依赖
- 3 核心代码
- 3.1 application 配置
- 3.2 实体类
- 3.3 基础增删改查(CRUD)
- 3.4 全文搜索(**重点**)
- 3.5 SpringBoot 启动类
- 4 注意事项
- 4.1 SpringBoot properties/yml 配置
- 4.2 字母大小写敏感问题
- 4.3 分词问题
- 5 推荐参考资料
- 6 Github 源码
Elasticsearch 是一款基于 Apache Lucene 的优秀的搜索服务器。本文将介绍基于 SpringBoot 2.5 集成 Elasticsearch 7 实现基本增删改查以及全文搜索。
Elasticsearch 官网: https://www.elastic.co
Elasticsearch 安装教程:
centOS 7 Elasticsearch 7.16 安装使用教程
2 核心 Maven 依赖./demo-elasticsearch/pom.xml
org.springframework.data spring-data-elasticsearch${elastic.springdata.version}
其中 ${elastic.springdata.version} 的版本为 4.3.0
其他相关依赖
org.springframework.boot spring-boot-starter-web${springboot.version} org.springframework.boot spring-boot-starter-validation${springboot.version} cn.hutool hutool-all${hutool.version} io.springfox springfox-boot-starter${springfox-swagger3.version}
版本信息
2.5.7 5.7.17 3.0.0
注意事项:
Swagger 3.0 不支持 SpringBoot 2.6+
Springfox 3.0.0 is not working with Spring Boot 2.6.0
3 核心代码 3.1 application 配置./demo-elasticsearch/src/main/resources/application.yml
## spring spring: application: name: demo-elasticsearch elasticsearch: rest: uris: 192.168.1.110:9200 username: elastic password: elastic666 connection-timeout: 10S read-timeout: 30S sniffer: interval: 5m delay-after-failure: 1m3.2 实体类
./demo-elasticsearch/src/main/java/com/ljq/springboot/elasticsearch/model/entity/BlogEntity.java
package com.ljq.springboot.elasticsearch.model.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.ToString; import org.springframework.data.elasticsearch.annotations.document; @Data @ToString(callSuper = true) @document(indexName = "blog") @ApiModel(value = "博客信息实体类", description = "博客信息实体类") public class BlogEntity extends baseEntity { private static final long serialVersionUID = -2124422309475024490L; @ApiModelProperty(value = "标题", name = "title") private String title; @ApiModelProperty(value = "作者", name = "author") private String author; @ApiModelProperty(value = "内容", name = "content") private String content; @ApiModelProperty(value = "阅读数量", name = "countRead") private Integer countRead; @ApiModelProperty(value = "点赞数量", name = "countLike") private Integer countLike; @ApiModelProperty(value = "客户端时间戳(精确到秒)", name = "clientTimestamp") private Integer clientTimestamp; }
./demo-elasticsearch/src/main/java/com/ljq/springboot/elasticsearch/model/entity/baseEntity.java
package com.ljq.springboot.elasticsearch.model.entity; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.LastModifiedDate; import java.io.Serializable; import java.util.Date; @Data public class baseEntity implements Serializable { private static final long serialVersionUID = -3003658740476069858L; @Id @ApiModelProperty(value = "id,主键", name = "id") private String id; @CreatedDate @ApiModelProperty(value = "创建时间", name = "createTime") private Long createTime; @LastModifiedDate @ApiModelProperty(value = "修改时间", name = "updateTime") private Date updateTime; }
org.springframework.data.elasticsearch.annotations.document 用于标注索引,类似于关系型数据库中的表名
org.springframework.data.annotation.Id 用于指定主键
org.springframework.data.elasticsearch.annotations.Field 用于指定字段,默认实体类中所有字段都会保存到 elasticsearch 中,所以可以不在字段上写这个注解
3.3 基础增删改查(CRUD)./demo-elasticsearch/src/main/java/com/ljq/springboot/elasticsearch/service/impl/BlogServiceImpl.java
package com.ljq.springboot.elasticsearch.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.ljq.springboot.elasticsearch.common.api.ApiMsgEnum; import com.ljq.springboot.elasticsearch.common.api.ApiResult; import com.ljq.springboot.elasticsearch.model.entity.BlogEntity; import com.ljq.springboot.elasticsearch.model.param.*; import com.ljq.springboot.elasticsearch.service.BlogService; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.QueryBuilders; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.support.PageableExecutionUtils; import org.springframework.stereotype.Service; import java.util.Objects; import java.util.stream.Collectors; @Slf4j @Service("blogService") public class BlogServiceImpl implements BlogService { @Autowired private ElasticsearchRestTemplate elasticTemplate; @Override public ApiResult3.4 全文搜索(重点)save(BlogAddParam addParam) { BlogEntity blogEntity = new BlogEntity(); BeanUtil.copyProperties(addParam, blogEntity, CopyOptions.create().ignoreError().ignoreNullValue()); elasticTemplate.save(blogEntity); return ApiResult.success(blogEntity); } @Override public ApiResult queryOne(BlogQueryOneParam queryOneParam) { return ApiResult.success(elasticTemplate.get(queryOneParam.getId(), BlogEntity.class)); } @Override public ApiResult update(BlogUpdateParam updateParam) { BlogEntity blogEntity = elasticTemplate.get(updateParam.getId(), BlogEntity.class); if (Objects.isNull(blogEntity)) { return ApiResult.fail(ApiMsgEnum.BLOG_NOT_EXIST); } BeanUtil.copyProperties(updateParam, blogEntity, CopyOptions.create().ignoreError().ignoreNullValue()); elasticTemplate.save(blogEntity); return ApiResult.success(blogEntity); } @Override public ApiResult delete(BlogDeleteOneParam deleteOneParam) { BlogEntity blogEntity = elasticTemplate.get(deleteOneParam.getId(), BlogEntity.class); if (Objects.isNull(blogEntity)) { return ApiResult.fail(ApiMsgEnum.BLOG_NOT_EXIST); } elasticTemplate.delete(deleteOneParam.getId(), BlogEntity.class); return ApiResult.success(); } }
./demo-elasticsearch/src/main/java/com/ljq/springboot/elasticsearch/service/impl/BlogServiceImpl.java
@Override public ApiResult3.5 SpringBoot 启动类> queryPage(BlogQueryPageParam queryPageParam) { Pageable pageable = PageRequest.of(queryPageParam.getCurrentPage() - 1, queryPageParam.getPageSize()); // 构建查询条件 NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder(); BoolQueryBuilder filter = QueryBuilders.boolQuery(); // id-精确查询-idsQuery if (StrUtil.isNotBlank(queryPageParam.getId())) { filter.must(QueryBuilders.idsQuery().addIds(queryPageParam.getId())); } // 标题-模糊查询-matchQuery if (StrUtil.isNotBlank(queryPageParam.getTitle())) { filter.must(QueryBuilders.matchQuery("title", queryPageParam.getTitle()).operator(Operator.OR).fuzziness(Fuzziness.AUTO)); } // 作者-精确查询-queryStringQuery if (StrUtil.isNotBlank(queryPageParam.getAuthor())) { filter.must(QueryBuilders.queryStringQuery( queryPageParam.getAuthor()).defaultField("author").fuzziness(Fuzziness.AUTO)); } // 内容-模糊查询-fuzzyQuery if (StrUtil.isNotBlank(queryPageParam.getContent())) { filter.must(QueryBuilders.fuzzyQuery("content", queryPageParam.getContent().toLowerCase()).fuzziness(Fuzziness.AUTO)); } // 全文查询-模糊查询-multiMatchQuery if (StrUtil.isNotBlank(queryPageParam.getKeyword())) { filter.must(QueryBuilders.multiMatchQuery( queryPageParam.getKeyword(),"title", "author", "content").fuzziness(Fuzziness.AUTO)); } // 客户端时间戳-范围查询-rangeQuery if (Objects.nonNull(queryPageParam.getMinClientTimestamp())) { filter.must(QueryBuilders.rangeQuery("clientTimestamp") .gte(queryPageParam.getMinClientTimestamp())); } if (Objects.nonNull(queryPageParam.getMaxClientTimestamp())) { filter.must(QueryBuilders.rangeQuery("clientTimestamp") .lte(queryPageParam.getMaxClientTimestamp())); } searchQueryBuilder.withFilter(filter); // 分页信息 searchQueryBuilder.withPageable(pageable); NativeSearchQuery query = searchQueryBuilder.build(); SearchHits searchHits = elasticTemplate.search(query, BlogEntity.class); log.info("搜索结果: {}n{}", searchHits, JSONUtil.toJsonStr(searchHits.getSearchHits())); Page page = PageableExecutionUtils.getPage(searchHits.getSearchHits().stream() .map(SearchHit::getContent).collect(Collectors.toList()),pageable, searchHits::getTotalHits); return ApiResult.success(page); }
./demo-elasticsearch/src/main/java/com/ljq/springboot/elasticsearch/DemoElasticsearchApplication.java
package com.ljq.springboot.elasticsearch; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.elasticsearch.config.EnableElasticsearchAuditing; @EnableElasticsearchAuditing @SpringBootApplication(scanbasePackages = "com.ljq.springboot.elasticsearch") public class DemoElasticsearchApplication { public static void main(String[] args) { SpringApplication.run(DemoElasticsearchApplication.class, args); } }4 注意事项 4.1 SpringBoot properties/yml 配置
SpringBoot elasticsearch 自动化配置类
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration
SpringBoot 2.5.7 :
SpringBoot 2.6.1 :
兼容性配置示例:
## spring spring: application: name: demo-elasticsearch elasticsearch: rest: uris: 192.168.1.110:9200 username: elastic password: elastic666 connection-timeout: 10S read-timeout: 30S sniffer: interval: 5m delay-after-failure: 1m4.2 字母大小写敏感问题
termQuery fuzzyQuery 区分大小写,推荐 *** 作方案: (1)在应用程序中将用户输入的搜索词统一转化为小写;(2) 在Elasticsearch 中添加转小写过滤器
spring-boot - 如何在 Elasticsearch 中搜索不匹配大小写的精确文本
4.3 分词问题matchQuery 只能匹配一个完整的单词,如果数据库中有 「spring」 这个单词,搜索条件为 「sprin」 则无法搜索到,而 fuzzyQuery 可以
elasticsearch 默认的中文分词是按照一个字一个字进行分词,英文分词则是按照一个完整的单词进行分词,如"黄鹤楼" 可以分出 “黄”,“鹤”,"楼"三个词;“springboot” 则就是一个单词
5 推荐参考资料Spring Data Elasticsearch - Reference documentation
Elasticsearch实战篇——Spring Boot整合ElasticSearch
Introduction to Spring Data Elasticsearch – Baeldung
SpringBoot Elasticsearch 7.x 多条件分页查询
ElasticSearch集成SpringData史上最全查询教程
Elasticsearch Queries with Spring Data
SpringBoot + ElasticSearch系列: springboot中使用QueryBuilders、NativeSearchQuery ElasticsearchRestTemplate 实现复杂查询
6 Github 源码Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo
个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)