当前位置:   article > 正文

ElasticSearch搜索引擎入门与实战_elasticsearch搜索引擎构建入门与实战

elasticsearch搜索引擎构建入门与实战

es简介

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

基本术语

  • 索引、类型、文档、字段 —对应 数据库 表 行 列
  • 集群、节点、分片、副本

es6.x以后,类型 将被废弃 索引直接与关系型数据库的表对应

项目使用的是springboot2.1.5,所以es需要使用6.4.3

安装es中文分词插件

SpringBoot整合Elasticsearch

引入依赖

spring-boot-starter-data-elasticsearch

配置Elasticsearch

cluster-name、cluster-nodes

image.png

配置完成之后需要注意一个小问题,如果项目中还有redis的话,在项目启动时会有冲突,因为redis与es底层都依赖于netty,解决方法:

@SpringBootApplication
public class CommunityApplication {
	//	@PostConstruct管理bean的初始化方法,在构造器调用完以后被执行
	@PostConstruct
	public void init(){
		//解决netty启动冲突问题
		//see Netty4Util
		System.setProperty("es.set.netty.runtime.available.processors","false");
	}

	public static void main(String[] args) {
		SpringApplication.run(CommunityApplication.class, args);
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Spring Dataa Elasticsearch

ElasticsearchTemplate

ElasticsearchRepository

项目中使用ElasticsearchRepository,首先需要将实体类映射至es,在实体类中加上注解,实例:

image.png

ok,简单将我们数据库字段映射之后,进行简单测试

  1. 单条数据插入

image.png

  1. 多条数据插入

image.png

  1. 单条数据删除

image.png

  1. 多条数据删除

image.png

  1. 使用Repository方式进行查询

image.png

使用此方式查询高亮显示内容无法插入到原数据中,所以选择Template来执行查询(因为高亮内容是单独的,所以需要手动替换)

  1. 使用Template方式进行查询并且添加关键字高亮显示

image.png

为了完成高亮显示功能,需要使用queryForPage方法,在SearchResultMapper中整合数据,具体看mapResults的操作

image.png

将数据依次封装,返回结果。

es应用

在项目中进行文章的检索功能

  • 搜索服务

    将帖子保存至Es服务器中
    从Es服务器删除帖子
    从Es服务器中搜索帖子

  • 发布事件

    发布帖子时,将帖子异步的提交到Es服务器
    增加评论时,将帖子异步提交到Es服务器
    在消费组件中增加一个方法,消费帖子发布事件。

  • 显示结果

    在控制器处理搜索请求,在HTML上显示搜索结果

编写Service,使用Repository加Template查询

/**
 * @author :LY
 * @date :Created in 2021/3/9 11:31
 * @modified By:
 */
@Service
public class ElasticsearchService {
    @Autowired
    private DiscussPostRepository discussRepository;

    @Autowired
    private ElasticsearchTemplate elasticTemplate;

    public void saveDiscussPost(DiscussPost discussPost){
        discussRepository.save(discussPost);
    }

    public void deleteDiscussPost(int id){
        discussRepository.deleteById(id);
    }
    public Page<DiscussPost> searchDiscussPost(String keyword, int current,int limit){
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(keyword,"title","content"))
                .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                .withPageable(PageRequest.of(current,limit))
                .withHighlightFields(
                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                        new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                ).build();

        return  elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                //首先通过searchResponse得到这次搜索得到的数据
                SearchHits hits = searchResponse.getHits();
                List<DiscussPost> list = new ArrayList<>();
                for (SearchHit hit : hits){
                    DiscussPost post = new DiscussPost();
                    String id = hit.getSourceAsMap().get("id").toString();
                    post.setId(Integer.valueOf(id));
                    String userId =  hit.getSourceAsMap().get("userId").toString();
                    post.setUserId(Integer.valueOf(userId));
                    String title = hit.getSourceAsMap().get("title").toString();
                    post.setTitle(title);
                    String content = hit.getSourceAsMap().get("content").toString();
                    post.setContent(content);
                    String status = hit.getSourceAsMap().get("status").toString();
                    post.setStatus(Integer.valueOf(status));
                    String createTime =  hit.getSourceAsMap().get("createTime").toString();
                    post.setCreateTime(new Date(Long.valueOf(createTime)));
                    String commentCount = hit.getSourceAsMap().get("commentCount").toString();
                    post.setCommentCount(Integer.valueOf(commentCount));
                    //处理高亮显示的结果
                    HighlightField titleField =  hit.getHighlightFields().get("title");
                    if (titleField != null){
                        post.setTitle(titleField.getFragments()[0].toString());
                    }
                    HighlightField contentField =  hit.getHighlightFields().get("content");
                    if (contentField != null){
                        post.setContent(contentField.getFragments()[0].toString());
                    }
                    list.add(post);
                }
                return new AggregatedPageImpl(list,pageable,
                        hits.getTotalHits(),searchResponse.getAggregations(),
                        searchResponse.getScrollId(),hits.getMaxScore());
            }
        });

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

controller编写

/**
 * @author :LY
 * @date :Created in 2021/3/9 15:21
 * @modified By:
 */
@Controller
public class SearchController {

    @Autowired
    private ElasticsearchService elasticsearchService;

    @Autowired
    private UserSerice userSerice;

    @Autowired
    private LikeService likeService;

    @GetMapping("/search")
    public String search(String keyword, Page page, Model model){
        //搜索
        org.springframework.data.domain.Page<DiscussPost> searchDiscussPost = elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());
        //聚合数据
        List<Map<String,Object>> discussPosts = new ArrayList<>();

        if(searchDiscussPost != null){
            searchDiscussPost.forEach(discussPost -> {
                Map<String,Object> map = new HashMap<>();
                //帖子
                map.put("post",discussPost);
                //作者
                map.put("user",userSerice.findUserById(discussPost.getUserId()));
                //点赞数量
                map.put("likeCount",likeService.findEntityLikeCount(CommunityConstant.ENTITY_TYPE_POST.getValue(), discussPost.getId()));

                discussPosts.add(map);
            });
        }
        model.addAttribute("discussPosts",discussPosts);
        model.addAttribute("keyword",keyword);

        //分页信息
        page.setPath("/search?keyword="+keyword);
        page.setRows(searchDiscussPost == null?0:(int) searchDiscussPost.getTotalElements());
        return "/site/search";

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

高亮效果
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/199658
推荐阅读
相关标签
  

闽ICP备14008679号