irpas技术客

SpringBoot2.6.x整合Elasticsearch7.17_天天debug..._elasticsearch笔记

大大的周 6948

SpringBoot2.6.x整合Elasticsearch7.17

Elasticsearch 简介:

一个分布式的,Restful 风格的搜索引擎。支持对各种类型的数据的检索。搜索速度快,可以提供实时的搜索服务。便于水平扩展,每秒可以处理 PB 级的海量数据。

Elasticsearch 术语:

索引,类型,文档,字段集群,节点,分片,副本

要想使用 es 搜索数据,前提是要在 es 中把数据再存一份。

索引(index):一个索引就是一个拥有几分相似特征的文档的集合(可以类比MySQL中的一个数据库)。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。 在一个集群中,如果你想,可以定义任意多的索引。类型(type):在一个索引中,你可以定义一种或多种类型(可以类比为MySQL数据库中的一张表,不过在新版本中type已经被废弃)。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。文档(document): 一个文档是一个可被索引的基础信息单元(可以类比MySQL表中的一条数据)。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。字段(field): JSON 风格的每一个属性叫做字段,对应与表中的列名。集群(cluster):一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。他们协同工作,共享数据并提供故障转移和扩展功能,当然一个节点也可以组成一个集群。节点(node):节点,一个运行的 ES 实例就是一个节点(也就是你集群中的一个服务器),作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。 在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。分片(shards): 一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。所以一个索引在存储的时候就可以拆成多个分片,每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。这样就大大提高了并发能力。副本(replicas):副本是对分片的备份(拷贝),一个分片可以包含多个副本。万一哪份备份数据出现了问题,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的,这就可以创建分片的一份或多份拷贝,提高了系统的可用性。

使用SpringBoot2.6.x集成Elasticsearch7.17

pom 文件 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> application.properties配置 # ElasticsearchProperties elasticsearch.host=127.0.0.1 elasticsearch.port=9200 Elasticsearch配置类 /** * Es配置类 * @ConfigurationProperties(prefix = "elasticsearch") * 自动读取关联application.properties中前缀为elasticsearch的属性 */ @ConfigurationProperties(prefix = "elasticsearch") @Configuration @Data public class ElasticsearchConfig extends AbstractElasticsearchConfiguration { private String host; private Integer port; // 重写父类方法 @Override public RestHighLevelClient elasticsearchClient() { RestClientBuilder builder = RestClient.builder(new HttpHost(host, port)); RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder); return restHighLevelClient; } } 实体类 @Data @NoArgsConstructor @AllArgsConstructor @ToString @Document(indexName = "discusspost", shards = 6, replicas = 3) public class DiscussPost { @Id private int id; // 用户id @Field(type = FieldType.Integer) private int userId; // 帖子的标题 eg.互联网校招 @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String title; // 帖子的内容 @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart") private String content; // type为帖子类型,0--普通帖子,1--置顶帖子,2--精华帖子 @Field(type = FieldType.Integer) private int type; // 帖子的状态,0--正常,1--精华,2--拉黑 @Field(type = FieldType.Integer) private int status; // 帖子创建的时间 @Field(type = FieldType.Date) private Date createTime; // 帖子评论的数量 @Field(type = FieldType.Integer) private int commentCount; // 记录帖子的分数 @Field(type = FieldType.Double) private double score; } 创建继承Elasticsearch的接口 @Repository public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost, Integer> { } 创建测试类 @RunWith(SpringRunner.class) @ContextConfiguration(classes = CommunityApplication.class) @SpringBootTest public class ElasticsearchTests { @Autowired private DiscussPostMapper discussPostMapper; // 实现crud等操作可以使用继承ElasticsearchRepository的接口,也可以使用ElasticsearchRestTemplate // 注入ElasticsearchRepository @Autowired private DiscussPostRepository discussPostRepository; // 注入ElasticsearchRestTemplate @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; // 插入一条数据 @Test public void testInsert() { discussPostRepository.save(discussPostMapper.selectDiscussPostById(241)); discussPostRepository.save(discussPostMapper.selectDiscussPostById(242)); discussPostRepository.save(discussPostMapper.selectDiscussPostById(243)); elasticsearchRestTemplate.save(); } // 插入多条数据 @Test public void testInsertList() { discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(101, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(102, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(103, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(111, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(112, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(131, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(132, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(133, 0, 100)); discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(134, 0, 100)); } // 修改一条数据 @Test public void testUpdate() { DiscussPost post = discussPostMapper.selectDiscussPostById(231); post.setContent("SpringBoot最新教程,快来围观!"); discussPostRepository.save(post); } // 删除一条(多条)数据 @Test public void testDelete() { discussPostRepository.delete(discussPostMapper.selectDiscussPostById(231)); //discussPostRepository.deleteAll(); } // 查询数据 @Test public void testSearchByRepository() { // withQuery()用于构造搜索条件 NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")) .withSorts(SortBuilders.fieldSort("type").order(SortOrder.DESC), SortBuilders.fieldSort("score").order(SortOrder.DESC), SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) .withPageable(PageRequest.of(0, 10)) .withHighlightFields( new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"), new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>") ).build(); Iterable<DiscussPost> discussPosts = discussPostRepository.findAll(); for (DiscussPost post : discussPosts) { System.out.println(post); } } // 查询数据并将关键字高亮显示 @Test public void testSearchByTemplate() { // withQuery()用于构造搜索条件 NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")) .withSorts(SortBuilders.fieldSort("type").order(SortOrder.DESC), SortBuilders.fieldSort("score").order(SortOrder.DESC), SortBuilders.fieldSort("createTime").order(SortOrder.DESC)) .withPageable(PageRequest.of(0, 10)) .withHighlightFields( new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"), new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>") ).build(); //查询 SearchHits<DiscussPost> search = elasticsearchRestTemplate.search(searchQuery, DiscussPost.class); long count = elasticsearchRestTemplate.count(searchQuery, DiscussPost.class); System.out.println("共查询到: "+ count +"条数据"); //得到查询返回的内容 List<SearchHit<DiscussPost>> searchHits = search.getSearchHits(); // 设置一个最后需要返回的实体类集合 List<DiscussPost> discussPosts = new ArrayList<>(); // 遍历返回的内容,进行处理 for (SearchHit<DiscussPost> hit : searchHits) { // 获取高亮的内容 Map<String, List<String>> highlightFields = hit.getHighlightFields(); // 将高亮的内容添加到content中(匹配到的如果是多段,就将第一段高亮显示) // 没有匹配到关键字就显示原来的title和content hit.getContent().setTitle(highlightFields.get("title")==null ? hit.getContent().getTitle():highlightFields.get("title").get(0)); hit.getContent().setContent(highlightFields.get("content")==null ? hit.getContent().getContent():highlightFields.get("content").get(0)); // 放到实体类中 discussPosts.add(hit.getContent()); } for (DiscussPost post : discussPosts) { System.out.println(post); } } }


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #elasticsearch笔记 #springboot #26x #集成 #es #717