• 分布式搜索引擎 ElasticSearch(ES)


    一、初识elasticsearch

    1.了解ES

    1)elasticsearch的作用

    elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容。elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK),被广泛应用在日志数据分析、实时监控等领域。而elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。

    2)elasticsearch和lucene

    elasticsearch底层是基于lucene来实现的。Lucene是一个Java语言的搜索引擎类库,是Apache公司的顶级项目,由DougCutting于1999年研发。官网地址:https://lucene.apache.org/

     3)elasticsearch与其他搜索技术对比

    虽然在早期,Apache Solr是最主要的搜索引擎技术,但随着发展elasticsearch已经渐渐超越了Solr,独占鳌头 。

    2.倒排索引

    1)正向索引

    如果是根据id查询,那么直接走索引,查询速度非常快。但如果是基于title做模糊查询,只能是逐行扫描数据,流程如下:

    1. 用户搜索数据,条件是title符合 "%手机%"
    2. 逐行获取数据,比如id为1的数据
    3. 判断数据中的title是否符合用户搜索条件
    4. 如果符合则放入结果集,不符合则丢弃。回到步骤1

    逐行扫描,也就是全表扫描,随着数据量增加,其查询效率也会越来越低。当数据量达到数百万时,就是一场灾难。

    • 优点:

      • 可以给多个字段创建索引

      • 根据索引字段搜索、排序速度非常快

    • 缺点:

      • 根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。

    2)倒排索引

    倒排索引中有两个非常重要的概念:

    • 文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息。

    • 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条。

    创建倒排索引是对正向索引的一种特殊处理,流程如下:

    • 将每一个文档的数据利用算法分词,得到一个个词条。

    • 创建表,每行数据包括词条、词条所在文档id、位置等信息。

    • 因为词条唯一性,可以给词条创建索引,例如hash表结构索引。

    如图:

    倒排索引的搜索流程如下(以搜索"华为手机"为例):

    1)用户输入条件 "华为手机" 进行搜索。

    2)对用户输入内容分词,得到词条:华为手机

    3)拿着词条在倒排索引中查找,可以得到包含词条的文档id:1、2、3。

    4)拿着文档id到正向索引中查找具体文档。

    如图:

     

    虽然要先查询倒排索引,再查询倒排索引,但是无论是词条、还是文档id都建立了索引,查询速度非常快!无需全表扫描。

    • 优点:

      • 根据词条搜索、模糊搜索时,速度非常快

    • 缺点:

      • 只能给词条创建索引,而不是字段

      • 无法根据字段做排序

    3.es的一些概念

    elasticsearch中有很多独有的概念,与mysql中略有差别,但也有相似之处。

    1)文档和字段

    elasticsearch是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中:

    而Json文档中往往包含很多的字段(Field),类似于数据库中的列。

    2)索引和映射

    索引(Index),就是相同类型的文档的集合。

    例如:

    • 所有用户文档,就可以组织在一起,称为用户的索引;

    • 所有商品的文档,可以组织在一起,称为商品的索引;

    • 所有订单的文档,可以组织在一起,称为订单的索引;

    可以把索引当做是数据库中的表。数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此,索引库中就有映射(mapping),是索引中文档的字段约束信息,类似表的结构约束。

    3)mysql与elasticsearch

     两者各自有自己的擅长支出:

    • MySQL:擅长事务类型操作,可以确保数据的安全和一致性

    • Elastic Search:擅长海量数据的搜索、分析、计算

    因此在企业中,往往是两者结合使用

    • 对安全性要求较高的写操作,使用mysql实现 

    • 对查询性能要求较高的搜索需求,使用elasticsearch实现

    • 两者再基于某种方式,实现数据的同步,保证一致性

    4.安装es、kibana

    详细可见:https://blog.csdn.net/yueyue763184/article/details/128138329?spm=1001.2014.3001.5501

    二、索引库操作

    索引库就类似数据库表,mapping映射就类似表的结构。要向es中存储数据,必须先创建“库”和“表”。

    1.mapping映射属性

    mapping是对索引库中文档的约束,常见的mapping属性包括:

    • type:字段数据类型,常见的简单类型有:

      • 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)

      • 数值:long、integer、short、byte、double、float、

      • 布尔:boolean

      • 日期:date

      • 对象:object

    • index:是否创建索引,默认为true

    • analyzer:使用哪种分词器

    • properties:该字段的子字段

    例如下面的json文档:

    1. {
    2.     "age"21,
    3.     "weight"52.1,
    4.     "isMarried"false,
    5.     "info""黑马程序员Java讲师",
    6.    "email""zy@itcast.cn",
    7.    "score": [99.1, 99.5, 98.9],
    8.     "name": {
    9.         "firstName""云",
    10.         "lastName""赵"
    11.     }
    12. }

    对应的每个字段映射(mapping):

    • age:类型为 integer;参与搜索,因此需要index为true;无需分词器

    • weight:类型为float;参与搜索,因此需要index为true;无需分词器

    • isMarried:类型为boolean;参与搜索,因此需要index为true;无需分词器

    • info:类型为字符串,需要分词,因此是text;参与搜索,因此需要index为true;分词器可以用ik_smart

    • email:类型为字符串,但是不需要分词,因此是keyword;不参与搜索,因此需要index为false;无需分词器

    • score:虽然是数组,但是我们只看元素的类型,类型为float;参与搜索,因此需要index为true;无需分词器

    • name:类型为object,需要定义多个子属性

      • name.firstName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器

      • name.lastName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器

    2.索引库的CRUD

    统一使用Kibana编写DSL的方式来操作。

    1)创建索引库和映射

    基本语法:

    • 请求方式:PUT
    • 请求路径:/索引库名,可以自定义
    • 请求参数:mapping映射

    例:

    1. # 创建索引库
    2. PUT /heima
    3. {
    4. "mappings": {
    5. "properties": {
    6. "info": {
    7. "type": "text",
    8. "analyzer": "ik_smart"
    9. },
    10. "email": {
    11. "type": "keyword",
    12. "index": false
    13. },
    14. "name": {
    15. "type": "object",
    16. "properties": {
    17. "firstName": {
    18. "type": "keyword"
    19. },
    20. "lastName": {
    21. "type": "keyword"
    22. }
    23. }
    24. }
    25. }
    26. }
    27. }

    创建成功:

    2)查询索引库

    基本语法

    • 请求方式:GET

    • 请求路径:/索引库名

    • 请求参数:无

    格式:GET /索引库名

     3)修改索引库

    倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改mapping。虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。

    语法说明

    1. PUT /索引库名/_mapping
    2. {
    3.   "properties": {
    4.     "新字段名": {
    5.       "type""integer"
    6.     }
    7.   }
    8. }

    4)删除索引库

    语法:

    • 请求方式:DELETE

    • 请求路径:/索引库名

    • 请求参数:无

    格式:DELETE /索引库名

    5)总结

    索引库操作有哪些?

    • 创建索引库:PUT /索引库名

    • 查询索引库:GET /索引库名

    • 删除索引库:DELETE /索引库名

    • 添加字段:PUT /索引库名/_mapping

    三、文档操作

    1.新增文档

    语法:

     例:

    1. POST /heima/_doc/1
    2. {
    3.     "info""黑马程序员Java讲师",
    4.     "email""zy@itcast.cn",
    5.     "name": {
    6.         "firstName""云",
    7.         "lastName""赵"
    8.     }
    9. }

    2.查询文档

    根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把文档id带上。

    3.删除文档

    删除使用DELETE请求,同样,需要根据id进行删除:

    4.修改文档

    修改有两种方式:

    • 全量修改:直接覆盖原来的文档

    • 增量修改:修改文档中的部分字段

    1)全量修改PUT

    全量修改是覆盖原来的文档,其本质是:

    • 根据指定的id删除文档

    • 新增一个相同id的文档

    注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。

    例:

    1. PUT /heima/_doc/1
    2. {
    3.     "info""黑马程序员高级Java讲师",
    4.     "email""zy@itcast.cn",
    5.     "name": {
    6.         "firstName""云",
    7.         "lastName""赵"
    8.     }
    9. }

    2)增量修改POST

    增量修改是只修改指定id匹配的文档中的部分字段。例:

    1. POST /heima/_update/1
    2. {
    3. "doc": {
    4. "email": "BuLiangShuai@itcast.cn"
    5. }
    6. }

    四、RestAPI

    ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html

    其中的Java Rest Client又包括两种:

    • Java Low Level Rest Client

    • Java High Level Rest Client

    整合步骤简介:

    1)引入es的RestHighLevelClient依赖:

    1. <dependency>
    2.    <groupId>org.elasticsearch.clientgroupId>
    3.    <artifactId>elasticsearch-rest-high-level-clientartifactId>
    4. dependency>

    2)因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

    1. <properties>
    2.    <java.version>1.8java.version>
    3.    <elasticsearch.version>7.12.1elasticsearch.version>
    4. properties>

    3)初始化RestHighLevelClient:

         初始化的代码如下:

    1. RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
    2.        HttpHost.create("http://192.168.119.130:9200")
    3. ));

    JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。

    索引库操作的基本步骤:

    • 初始化RestHighLevelClient

    • 创建XxxIndexRequest。XXX是Create、Get、Delete

    • 准备DSL( Create时需要,其它是无参)

    • 发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete

  • 相关阅读:
    达梦数据库如何收集统计信息?
    vmware fusion12共享文件夹到虚拟机window10
    PIL库的crop函数(图片裁剪操作)
    元宇宙攻略:手把手教你创建一个(去中心化自治组织)DAO
    LongLoRA:超长上下文,大语言模型高效微调方法
    Windows-Oracle11g 安装详解-含Navicate远程连接配置 -本地监听设置及更换navicate环境指向的oci.dll
    大学生游戏静态HTML网页设计 (HTML+CSS+JS仿英雄联盟网站15页)
    计算机毕业设计 JSPM校园闲置物品交易平台的设计与实现 Java实战项目 附源码+文档+视频讲解
    操作系统进程调度算法的模拟实现(c语言版本)
    grid网格布局,比flex方便太多了,介绍几种常用的grid布局属性
  • 原文地址:https://blog.csdn.net/yueyue763184/article/details/128133918