ElasticSearch总结1

本文详细介绍了ElasticSearch的基本概念、与MySQL的对比,重点讲解了正向索引和倒排索引的区别,以及为何在Elasticsearch中安装Kibana和IK分词器。通过实例展示了如何设置映射和优化中文分词,包括IK分词器的Smart和MaxWord模式。
摘要由CSDN通过智能技术生成

目录

一、ElasticSearch介绍:

举例一:

举例二:

举例三:

二、ELK技术栈

三、Elasticsearch 的基本概念:

四、正向索引和倒排索引:

正向索引:

倒排索引:

五、Mysql和Elasticsearch对比

六、安装单体ES和kibana、IK分词器

为什么要去安装kibana:

为什么要去安装IK分词器:

代码:

代码: 

代码: 

IK分词器拓展词库:

ik分词器-停用词库 :

 七、Mapping属性详细介绍:

mapping常见的属性: 

注意事项: 


一、ElasticSearch介绍:

        ElasticSearch是一个非常强大的开源搜索引擎。它可以帮助我们从海量数据中快速的找到所需要的内容。这个搜索引擎可以用来实现搜索、日志、统计分析等监控等等功能。

        而且这个索引擎是一个分布式的搜素引擎,它能够支持这种水平的扩展,形成集群

  ElasticSearch的底层实现是基于Lucene技术。Lucene是一个java语言的搜索引擎,Lucene是Apache公司的一个顶级项目,而ElasticSearch,正是基于这个Lucene去做的二次开发

        Lucene是apache公司的一个搜索引擎类库,也就是一个jar包,里面有里面有各种各样的a p i.

        将来在mysql里边我们sql写好了,通过这个connection,把这个东西给它发出去,发给mysql,mysql是不是就处理了?那在ES当中呢,你写了DSL以后,你要通过什么发出去呢?是基于h t t p的请求发出去的,为什么呢?因为在我们ES里,它对外暴露的是Restful接口嘛,这种接口的处是跟语言无关。也就是说你任何的语言,你只要能发h t t p请求,你都可以把你的DSL发给我,我就能处理了。

        这样一来,他就彻底脱离了语言的束缚了

举例一:

        例如去github网站上搜索一些仓库, 当你去搜索的时候,它不仅仅能够把相关仓库给你搜出来,还能够把你所搜索的这个关键字,它所在的这个代码也给你高亮展示出来:

举例二:

        京东上买东西,输入商品的信息,立马能够搜索出跟你输入关键字有关的这些商品,并且高亮显示:

举例三:

        google搜索代码报错的异常信息:

二、ELK技术栈

        Elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域:

  • elasticsearch是elastic stack的核心,负责数据的搜素、分析和运算
  • Logstash、Beats, 这两个组件主要是来负责数据抓取的。比如说你的日志数据,就可以由他来去抓取。  
  • kibana是一个数据可视化的组件。将来搜索出来的数据要展示,可以用它来去展示,形成报表

        例如百度、京东在展示结果的时候,都有自己的网站,所以这种可视化不一定非得用这个kibana去做。你完全可以自己去实现;数据抓取也一样,我们完全可以自己写java代码,自己从数据库中获取数据。然后往ElasticSearch里去写

        所以kibana、Logstash、Beats,它们都是可替换的一个组件,官方提供给你,你想用就用,你不用也没关系,但是不可替代的就是ElasticSearch。

三、Elasticsearch 的基本概念:

(1)index 索引:索引类似于数据库中的表,Elasticesearch 中的索引是存储数据的地方,索引就是相同类型文档的集合。

(2)映射(mapping)︰索引中文档的字段约束信息(字段名、数据类型)类似表的结构约束;每个索引库都应该有自己的映射 

(3)type 类型:类型是用来定义数据结构,可以认为是 mysql 中的一张表,type 是 index 中的一个逻辑数据分类

(4)document 文档:类似于 MySQL 中的一行。文档是es中的最小数据单元,每一条数据就是一个文档,ES中的文档是jason风格的

(5)词条:使用分词器对文档中的内容分词,得到的词语就是词条

(6)Field 字段:Field是Elasticsearch的最小单位,一个document里面有多个field

(7)shard 分片:单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个分片,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。

(8)replica 副本:任何服务器随时可能故障或宕机,此时 shard 可能会丢失,通过创建 replica 副本,可以在 shard 故障时提供备用服务,保证数据不丢失,另外 replica 还可以提升搜索操作的吞吐量。

        shard 分片数量在建立索引时设置,设置后不能修改,默认5个;replica 副本数量默认1个,可随时修改数量;

 (9)DSL:DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD 

   (10)分词器的作用: ①、创建倒排索引时对文档分词;  ②、用户搜索时, 对输入的内容分词

四、正向索引和倒排索引:

正向索引:

        比方说我这里有一张数据库表,那我们知道对于数据库它一般情况下都会基于i d去创建索引,然后形成一个b+树,当用户根据id(索引字段)进行检索的速度非常快,但是当用户进行局部内容检索,模糊查询的时候,索引将会失效,这时候数据库只能采用逐条扫描的方式来判断每一行数据中是否包含用户搜素的内容,包含的话就存入查询结果集,当数据库中的存储了海量数据的时候,逐条检索的效率非常低,性能非常差,这就是正向索引:

         搜索'手机":

        select *from tb_goods where title like'%手机%'

倒排索引:

         ①、倒排索引,ES在存储文档时,它首先会先对文档的内容按照词义分成一个一个不同词条,对词条创建索引,并记录词条所在文档的id;

        ②、当我们去做搜素、查询的时候会涉及到两次查询:第一次查询是先根据用户输入的内容按照词义分成一个个词条,然后去词条列表中进行搜素,找到对应的文档id,由于所有的词条都建立了索引,所以基于词条来查询文档id的速度是非常快的;第二次查询是拿着文档id找到具体文档,再存入查询结果集,返回给前端。

         ③、虽然经历了两次搜查询,但每一次都是根据索引进行查询,所以总的查询效率是比传统的正向索引:逐条扫描要高很多,时间复杂度是O(1),极大的提高了检索效率。

  • 正向索引是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条扫描获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程

  • 倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程

五、Mysql和Elasticsearch对比

        Mysql和Elasticsearch擅长的事情是不一样的。MySQL支持事务,它更擅长的是事物类型的操作:因为事物里边有ACID的原则,所以它是可以确保数据的ACID 安全性、一致性

        ES没有事物的概念,所以它无法保证数据的ACID,它更擅长的是数据的搜索、分析和运算。

        所以它们两个是各司其职的。如果你的业务对数据的安全性、一致性要求很高,你就应该使用mysql去做数据存储。  如果你的业务涉及到了海量数据的搜素、面对比较复杂的搜素业务场景,就是用ES。

六、安装单体ES和kibana、IK分词器

        DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

为什么要去安装kibana:

        为什么还要去安装kibana? 因为kibana里边提供了一个dev tools工具,可以让我们非常方便的去编写ES中的DSL语句,发送DSL语句,从而去操作ES,它的本质其实就是发送一个Restful的请求到ES当中。

        安装单体ES和kibana、IK分词器具体看我这篇博客:

Docker安装部署ElasticSearch-CSDN博客

        我们刚刚在创建Kibana容器的时候,指定了ES的地址,所以这里你把DSL语句准备好,请求方式和路径准备好,kibana就帮你把这个DSL发给ES,很方便,你不用去指定ES的ip地址和端口号了: 

GET /:判断ES是否连接

       

为什么要去安装IK分词器:

        ES在创建倒排索引时,需要对文档内容进行分词。而且我们在去搜索时需要对用户输入的内容也去做分词。分词就需要对中文或者是英文的语义进行分析,按照词语含义进行拆分。这种拆分其实是比较复杂的,需要有特殊的算法去支持,但默认的分词规则对中文处理并不友好:

代码:

POST /_analyze
{
  "analyzer": "standard",
  "text": "猪大肠吃起来good!"
}

{
  "tokens" : [
    {
      "token" : "猪",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "大",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "肠",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "吃",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "起",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "来",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    },
    {
      "token" : "good",
      "start_offset" : 6,
      "end_offset" : 10,
      "type" : "<ALPHANUM>",
      "position" : 6
    }
  ]
}

        处理中文分词,一般会使用IK分词器, ik分词器包含两种模式:

  •          ik_smart:        最少切分,粗粒度
  •          ik_max_word: 最细切分,细粒度
代码: 

POST /_analyze
{
  "analyzer": "ik_max_word",
  "text": "程序员太棒了"
}
{
  "tokens" : [
    {
      "token" : "程序员",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "程序",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "员",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "CN_CHAR",
      "position" : 2
    },
    {
      "token" : "太棒了",
      "start_offset" : 3,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "太棒",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "了",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "CN_CHAR",
      "position" : 5
    }
  ]
}
代码: 

POST /_analyze
{
  "analyzer":"ik_smart",
  "text": "程序员太棒了"
}

      ik_smart是粗力度切分:它会从字数最多开始往字数越来越少去看,首先看五个字是不是一个词,如果不是,我再看四个,如果还不是,再看三个,如果发现程序员这三个字刚好是一个词,我就不再继续往下看两个字是不是词。

      ik_max_word分出来有三个词: 程序、程序员、员,那用户搜索的时候,我无论输入 程序、程序员还是员,这三个词中的任意一个都能搜这个文档,但是如果你采用的是ik_smart,你分出来只有程序员这一个词,那搜到的概率就会比较低。

      ik_smart优缺点:分的词少了,占用的内存空间就小一些,将来内存里可以缓存更多的数据。但是被搜到的概率就会比较低

        ik_max_word优缺点:占用内存空间会更多,被搜索到的概率更大 

思考:

      IK分词器它底层分词的原理到底是什么? 他怎么知道程序员这三个字合在一起是一个词呢? 它的底层一定会有一个字典,在这个字典里边一定会有各种各样的词语,提前在里边就罗列了。当他要分词的时候,他肯定是拿着这些字去匹配,看那个词典里有没有。如果匹配到发现这俩在里边有证明它是个词,那就把它分出来。所以不管是IK分词器,还是其他的中文分词器,它都会依赖于一个字典来去做分词。但这个字典不可能罗列出所有的词语,因为每年都有网络词语诞生:

POST /_analyze
{
  "analyzer":"ik_smart",
  "text": "奥里给"
}

        ”的、啊、呢“这样的词语,这种词分类没有什么意义,还有一些敏感词汇,比如说国家领导人的名字或者禁忌、一些毒品之类的,要把它禁掉, 所以ik分词器能不能实现这种字典的个性化设置呢,能!

IK分词器拓展词库:

          IK分词器支持这种词库的拓展。拓展方式是找到它的config目录下的:

ik分词器-停用词库 :

步骤: 

  打开以后呢,在这里大家可以看到,这个就是扩展字典,这个是停止词:

这两个其实是文件名:

        也就是说拓展字典要来读这个文件,停止词字典要来读这个文件。

 这个两个文件在哪呢?它是在当前配置文件所在目录,在这个目录里面把这两个文件新建起来:

                                

                         

        这个文件打开之后就有英文里边的一些冠词介词之类的、无意义的词语。我们也可以把咱们中文的一些无意义词语、语气词、禁用词加进去:

                

配置好了以后,重启让它生效:

               docker  restart  es

 七、Mapping属性详细介绍:

        映射(mapping)︰索引中文档的字段约束信息(字段名、数据类型)类似表的结构约束;每个索引库都应该有自己的映射          

        数据库一定要先创建表才能去添加数据。ES里面也一样,你得先有了索引库才能往里边去添加文档,要想去创建一个索引库,就像建表一样,建表语句里面是要指定个schemer,也就是对字段的一些约束。我们的索引库它在创建时需要去指定对应的mapping映射: 对文档的约束。

mapping常见的属性: 

       ES中的文档是jason风格的,作为一个jason,它里面要么是数值,要么是布尔值,要么是字符串,要么数组,要么是对象嵌套。这些类型对应到我们的这个ES中都有对应的一个类型去进行约束:

注意事项: 
  • text是可分词的文本,比如说我这里的info,info是个人信息;
  • keyword是精确值,它只有合在一起才有意义,不能拆开,如邮箱;
  • index代表是否创建倒排索引,为true,就会给你创建倒排索引,就可以参与搜索了,如果说这儿给了false,就不会倒排索引,就没有办法去搜索这个字段。 它的默认值就是ture,也就是说你在做字段映射时,如果你不去设置index,默认所有的字段都会被创建倒排索引,将来每个字段都可以参与搜索。
  • 我们在实际开发的过程中,不是所有的字段都需要搜索,比如邮箱、商品的图片是一个url地址,没有搜索意义。

  • analyzer其实是结合text类型去用的,所有数据类型里,只有text类型需要分词,其他所有类型都无需分词

  • 在ES当中是没有数组这种类型,但是它允许你某一个类型的字段有多个值,比如说你是一个部门类型,但是你里边有多个值没问题,数据类型要一致

                                

       Object将来要结合Properties声明子字段 ,Properties是该字段的子字段。例如name有两个子属性:firstName 、 lastName, 将来我就可以用property来指定name的子属性:

                        ​​​​​​​        ​​​​​​​        ​​​​​​​        

  • 32
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值