Elasticsearch7.6x 学习

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
    }
  ]
}

命令模式使用

methodurl地址描述
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)
POSTlocalhost:9200/索引名称/类型名称创建文档(随机文档id)
POSTlocalhost:9200/索引名称/类型名称/文档id/_update修改文档
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档
GETlocalhost:9200/索引名称/类型名称/文档id通过文档id查询文档
POSTlocalhost:9200/索引名称/类型名称/_search查询所有的数据

SpringBoot 集成Elcticsearch

配置类:

/**
 * SpringBoot与Elasticsearch集成
 * 之后,用这个client对象就可以了
 */
@Configuration
public class ElasticsearchClientConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")));
        return client;
    }
}

搜索test

    @Autowired
    public RestHighLevelClient restHighLevelClient;

    @Test
    void 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
    @Autowired
    public RestHighLevelClient restHighLevelClient;

    //获取数据实现搜索功能
    public List<Map<String,Object>> searchPage(String keyword,int pageNo,int pageSize) throws IOException {
        if (pageNo <= 1) {
            pageNo = 1;
        }

        //搜索条件   eg: goods
        SearchRequest 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: goods
        SearchRequest 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);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值