当前位置: 代码迷 >> 综合 >> Elasticsearch7.6x 学习
  详细解决方案

Elasticsearch7.6x 学习

热度:2   发布时间:2023-12-12 03:17:23.0

文章目录

  • Elasticserach
  • WHAT
  • WHY
  • HOW
    • 命令模式使用
    • SpringBoot 集成Elcticsearch

Elasticserach

WHAT

Elasticsearch分布式全文搜索引擎

它可以高效的 存储 和 检索 数据。

es 是使用 Java语言开发的,并且基于 Lucene,es 通过简单的RESTful API 来隐藏 Lucene的复杂性,从而使得全文搜索变得简单。

es 是 lucene 的封装,提供了RESTful API 的操作接口,开箱即用。

同类“竞品”

Solr:是一个高性能,采用 Java 开发,基于Lucene的全文搜索服务器。它对外提供类似于web-service的API接口。

es 与 solr

  • es基本是开箱即用,非常简单。而solr会有点复杂
  • solr利用Zookeeper进行分布式管理,而elasticsearch自身带有分布式协调管理功能
  • solr支持更多格式的数据,比如json xml csv。而es只支持json文件格式(够用)
  • solr官方提供的功能更多,而elasticsearch更注重核心功能,高级功能由第三方插件提供
  • solr查询快,但更新索引时慢,用于电商等查询多的应用
  • es建立索引宽,即实时性查询快,用于facebook新浪等搜索
  • solr较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而elasticsearch相对开发维护者较少,更新太快,学习使用成本较高

WHY

使用数据库 来做搜索业务,不能很好的满足需求。

虽然某一程度上也可以视为数据库,但是它更主要的身份还是一个优秀的全文搜索引擎。它的出现解决了一部分传统关系型数据库和NoSQL非关系型数据库所没有办法高效完成的一些工作,比如高效的全文检索,结构化检索,甚至是数据分析。

响应时间

eg:数据库在做模糊查询时,如LIKE 语句,它会遍历整张表,同时进行字符串匹配。

es 是基于 倒排索引 的 ,检索速度非常快。

分词

Elasticsearch支持中文分词插件 IK

相关性

Elasticsearch 支持全文搜索和相关度评分。这样在返回结果就会根据分数由高到低排列。分数越高,意味着和查询语句越相关。

可视化界面

MySQL 的 Navicat

Elasticsearch 的 Kibana

HOW

Elasticsearch 中的概念:

Index:索引(相当于数据库)

Document:文档(一条条记录)

注意:高版本可以可能会舍弃 type,创建的时候可以设置为默认(_doc)

IK分词器

默认的中文分词,是将每个字看成一个词,显然不符合需求,所以,需要安装中文分词器ik来解决问题。

IK 提供了两个分词算法:ik_smartik_max_word

  • ik_smart:最少切分
  • ik_max_word:最细粒度切分

eg:

GET _analyze
{
    "analyzer": "ik_smart","text": "我是社会主义接班人"
}//输出
{
    "tokens" : [{
    "token" : "我","start_offset" : 0,"end_offset" : 1,"type" : "CN_CHAR","position" : 0},{
    "token" : "是","start_offset" : 1,"end_offset" : 2,"type" : "CN_CHAR","position" : 1},{
    "token" : "社会主义","start_offset" : 2,"end_offset" : 6,"type" : "CN_WORD","position" : 2},{
    "token" : "接班人","start_offset" : 6,"end_offset" : 9,"type" : "CN_WORD","position" : 3}]
}
GET _analyze
{
    "analyzer": "ik_max_word","text": "我是社会主义接班人"
}
//输出
{
    "tokens" : [{
    "token" : "我","start_offset" : 0,"end_offset" : 1,"type" : "CN_CHAR","position" : 0},{
    "token" : "是","start_offset" : 1,"end_offset" : 2,"type" : "CN_CHAR","position" : 1},{
    "token" : "社会主义","start_offset" : 2,"end_offset" : 6,"type" : "CN_WORD","position" : 2},{
    "token" : "社会","start_offset" : 2,"end_offset" : 4,"type" : "CN_WORD","position" : 3},{
    "token" : "主义","start_offset" : 4,"end_offset" : 6,"type" : "CN_WORD","position" : 4},{
    "token" : "接班人","start_offset" : 6,"end_offset" : 9,"type" : "CN_WORD","position" : 5},{
    "token" : "接班","start_offset" : 6,"end_offset" : 8,"type" : "CN_WORD","position" : 6},{
    "token" : "人","start_offset" : 8,"end_offset" : 9,"type" : "CN_CHAR","position" : 7}]
}

命令模式使用

method url地址 描述
PUT localhost:9200/索引名称/类型名称/文档id 创建文档(指定文档id)
POST localhost:9200/索引名称/类型名称 创建文档(随机文档id)
POST localhost:9200/索引名称/类型名称/文档id/_update 修改文档
DELETE localhost:9200/索引名称/类型名称/文档id 删除文档
GET localhost:9200/索引名称/类型名称/文档id 通过文档id查询文档
POST localhost:9200/索引名称/类型名称/_search 查询所有的数据

SpringBoot 集成Elcticsearch

配置类:

/*** SpringBoot与Elasticsearch集成* 之后,用这个client对象就可以了*/
@Configuration
public class ElasticsearchClientConfig {@Beanpublic RestHighLevelClient restHighLevelClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));return client;}
}

搜索test

    @Autowiredpublic RestHighLevelClient restHighLevelClient;@Testvoid testSearch() throws IOException {
    SearchRequest searchRequest = new SearchRequest();//构建搜索条件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//构建高亮// searchSourceBuilder.highlighter();//查询条件,可以使用 QueryBuilders 工具来实现 精确查询 QueryBuilders.termQuery()TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "damin");//匹配全部//MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();searchSourceBuilder.query(termQueryBuilder);//设置分页//不设置 SearchSourceBuilder 也有默认值//searchSourceBuilder.from();//searchSourceBuilder.size();//设置搜索时间,(时间不要超过多少)searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//放到请求中searchRequest.source(searchSourceBuilder);//执行请求SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// searchResponse.getHits() //所有的结果都封装在 SearchHits -> getHits//遍历for (SearchHit documentFields : searchResponse.getHits().getHits()) {
    System.out.println(documentFields.getSourceAsMap());}}

爬取京东商品页面实例部分代码

视频:遇见狂神说

//普通搜索Service@Autowiredpublic RestHighLevelClient restHighLevelClient;//获取数据实现搜索功能public List<Map<String,Object>> searchPage(String keyword,int pageNo,int pageSize) throws IOException {
    if (pageNo <= 1) {
    pageNo = 1;}//搜索条件 eg: goodsSearchRequest searchRequest = new SearchRequest("索引");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//分页sourceBuilder.from(pageNo);sourceBuilder.size(pageSize);//精准匹配TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);sourceBuilder.query(termQueryBuilder);sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//执行搜索searchRequest.source(sourceBuilder);//通过客户端进行查询SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//解析结果ArrayList<Map<String,Object>> list = new ArrayList<>();for (SearchHit documentFields : searchResponse.getHits().getHits()) {
    //把 documentFields结果 变成map 返回list.add(documentFields.getSourceAsMap());}return list;}
//高亮显示public List<Map<String,Object>> searchPageHighlightBuilder(String keyword,int pageNo,int pageSize) throws IOException {
    if (pageNo <= 1) {
    pageNo = 1;}//搜索条件 eg: goodsSearchRequest searchRequest = new SearchRequest("索引");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//分页sourceBuilder.from(pageNo);sourceBuilder.size(pageSize);//精准匹配TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);sourceBuilder.query(termQueryBuilder);sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//高亮HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");highlightBuilder.requireFieldMatch(false);   //多个高亮显示highlightBuilder.preTags("<span style='color:red'>");//前缀标签highlightBuilder.postTags("</span>"); //后缀标签//标签,vue解析 :v-html=""sourceBuilder.highlighter(highlightBuilder);//执行搜索searchRequest.source(sourceBuilder);//通过客户端进行查询SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//解析结果ArrayList<Map<String,Object>> list = new ArrayList<>();for (SearchHit documentFields : searchResponse.getHits().getHits()) {
    //获取高亮字段Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();HighlightField title = highlightFields.get("title");//原来的结果 把原来没有高亮的字段 => 替换为有高亮的字段Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();//解析高亮字段if (title != null) {
    Text[] fragments = title.fragments();String n_title = "";for (Text text : fragments) {
    n_title += text;}sourceAsMap.put("title",n_title);}list.add(sourceAsMap);}return list;}

Controller

 @GetMapping("/search/{keyword}/{pageNo}/{pageSize}")public List<Map<String,Object>> search(@PathVariable("keyword") String keyword,@PathVariable("pageNo") int pageNo,@PathVariable("pageSize") int pageSize) throws IOException {
    //一些基本业务,比如没有传到值if (pageNo == 0){
    }return contentService.searchPage(keyword,pageNo,pageSize);}