【ElasticSearch】ElasticSearch 快速入门(精讲)

如果你觉得官网下载很慢,那么你可以去华为云的镜像去下载,速度很快,自己找对应版本就可以。
ElasticSearch: https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D
logstash: https://mirrors.huaweicloud.com/logstash/?C=N&O=D
kibana: https://mirrors.huaweicloud.com/kibana/?C=N&O=D

提示:你的换用中要有Node.js、Python和jdk1.8+的环境,我们的elasticsearch的环境是7.6.1版本的,安装的时候一定要注意版本统一


一、ElasticSearch 的安装

1、安装

对于ElasticSearch的安装,我们只需要解压就可以
在这里插入图片描述

2、目录介绍

在这里插入图片描述

bin:启动目录
config:配置目录
	log4j2.properties:日志配置文件
	jvm.options:java虚拟机配置文件
	elasticsearch.yml:elasticsearch配置文件
jdk:javajdk
lib:相关jar包
log:日志
modules:功能模块
plugins:插件

3、启动

双击 D:\environment\elasticsearch\elasticsearch-7.6.1\bin\elasticsearch.bat
在这里插入图片描述
我们可以看到开始有这么一句话,提示我们的jdk1.8版本太低,提示我们使用更新的版本,所以,要求你的jdk最低是1.8
在这里插入图片描述
elasticsearch的路由端口是9300,公有地址是9200
在这里插入图片描述

4、访问

访问http://127.0.0.1:9200/
在这里插入图片描述

二、head 的安装(可视化界面)

head是elasticsearch的可视化工具,是准备针对elasticsearch的客户端

1、下载

https://github.com/mobz/elasticsearch-head中下载head插件,选择下载zip
在这里插入图片描述

解压即可
在这里插入图片描述

2、安装

官方的安装步骤(你的电脑中一定要安装了Node.js)
在这里插入图片描述

npm install 或 cnpm install
在这里插入图片描述
在这里插入图片描述

3、启动

npm run start
在这里插入图片描述
访问:http://localhost:9100,连接(会存在跨域问题)
在这里插入图片描述

解决跨域问题:关闭elasticsearch,配置elasticsearch.yml文件

# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true

http.cors.enabled: true			# 配置开启跨域
http.cors.allow-origin: "*"		# 允许所有人访问

重启elasticsearch,访问http://127.0.0.1:9200/
在这里插入图片描述

访问:http://localhost:9100,连接(成功)
在这里插入图片描述

建立索引
ElasticSearch是文档型数据库,索引(Index)定义了文档的逻辑存储和字段类型,每个索引可以包含多个文档类型,文档类型是文档的集合,文档以索引定义的逻辑存储模型。我们可以认为索引就是一个库就可以,其中可以存储信息
在这里插入图片描述

三、kibana 的安装

Kibana 是一款免费开源的前端应用程序,其基础是 Elastic Stack,可以为 Elasticsearch 中索引的数据提供搜索和数据可视化功能。尽管人们通常将 Kibana 视作 Elastic Stack(之前称作 ELK Stack,分别表示 Elasticsearch、Logstash 和 Kibana)的制图工具,但也可将 Kibana 作为用户界面来监测和管理 Elastic Stack 集群并确保集群安全性,还可将其作为基于 Elastic Stack 所开发内置解决方案的汇集中心

1、安装

对kibana的安装,我们只需要解压即可
在这里插入图片描述

2、启动

双击D:\environment\elasticsearch\kibana-7.6.1-windows-x86_64\binkibana.bat
在这里插入图片描述
默认端口为5601
在这里插入图片描述
访问http://localhost:5601/
在这里插入图片描述

开发工具(我们的查询代码基本上都会在这里写)
在这里插入图片描述

3、汉化

我们可看到在这里有一个中文的json
在这里插入图片描述
设置汉化
配置kibana-7.6.1-windows-x86_64\config\kibana.yml
在这里插入图片描述
重启kibana(汉化成功)
在这里插入图片描述

四、ES 工作原理

1、介绍

先说Elasticsearch的文件存储,Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式,比如下面这条用户数据:

{
    "name" :     "studioustoger",
    "sex" :      "male",
    "age" :      18,
    "birthDate": "2020/05/01",
    "about" :    "I love to sleep,
    "interests": [ "sports", "music" ]
}

用Mysql这样的数据库存储就会容易想到建立一张User表,有各种各样的字段,在Elasticsearch里这就是一个文档,当然这个文档会属于一个User的类型,各种各样的类型存在于一个索引当中。这里有一份简易的将Elasticsearch和关系型数据术语对照表:

关系数据库     ⇒ 数据库 ⇒ 表    ⇒ 行    ⇒ 列(Columns)

Elasticsearch  ⇒ 索引(Index)   ⇒ 类型(type)  ⇒ 文档(Docments)  ⇒ 字段(Fields)  

一个 Elasticsearch 集群可以包含多个索引(数据库),也就是说其中包含了很多类型(表)。这些类型中包含了很多的文档(行),然后每个文档中又包含了很多的字段(列)。Elasticsearch的交互,可以使用Java API,也可以直接使用HTTP的Restful API方式,比如我们打算插入一条记录,可以简单发送一个HTTP的请求:

PUT /demo/user/1
{
    "name" :     "studioustoger",
    "sex" :      "male",
    "age" :      18,
    "birthDate": "2020/05/01",
    "about" :    "I love to sleep,
    "interests": [ "sports", "music" ]
}

至于更新和查询,也是类似的操作,在这里就不展开讲了,后面会详细的讲…


2、索引

Elasticsearch最关键的就是提供强大的索引能力了,其实InfoQ的这篇时间序列数据库的秘密(2)——索引写的非常好,我这里也是围绕这篇结合自己的理解进一步梳理下,也希望可以帮助大家更好的理解这篇文章。

Elasticsearch索引的精髓:一切设计都是为了提高搜索的性能

另一层意思:为了提高搜索的性能,难免会牺牲某些其他方面,比如插入/更新,否则其他数据库不用混了。前面看到往Elasticsearch里插入一条记录,其实就是直接PUT一个json的对象,这个对象有多个fields,比如上面例子中的name, sex, age, about, interests,那么在插入这些数据到Elasticsearch的同时,Elasticsearch还默默1的为这些字段建立索引–倒排索引,因为Elasticsearch最核心功能是搜索。

Elasticsearch是如何做到快速索引的
InfoQ那篇文章里说Elasticsearch使用的倒排索引比关系型数据库的B-Tree索引快,为什么呢?

什么是B-Tree索引?
上大学读书时老师教过我们,二叉树查找效率是logN,同时插入新的节点不必移动全部节点,所以用树型结构存储索引,能同时兼顾插入和查询的性能。因此在这个基础上,再结合磁盘的读取特性(顺序读/随机读),传统关系型数据库采用了B-Tree/B+Tree这样的数据结构:
在这里插入图片描述
为了提高查询的效率,减少磁盘寻道次数,将多个值作为一个数组通过连续区间存放,一次寻道读取多个数据,同时也降低树的高度。

什么是倒排索引?
Elasticsearch最强大的就是为每个字段提供了倒排索引,当查询的时候不用担心没有索引可以利用,什么是倒排索引,举个简单例子:
在这里插入图片描述
每一行是一个文档(document),每个document都有一个文档ID。那么给这些文档建立的倒排索引就是:

年龄的索引:
在这里插入图片描述
性别的索引:
在这里插入图片描述
可以看到,倒排索引是针对每个字段的,每个字段都有自己的倒排索引,25、32、男、女这些叫做term,[1,3]、[1,2]这种叫做posting list

它是一个int的数组,存储了所有符合某个term的文档id,这时候我们想找出年龄为25的人,就会很快速,但是这里只有两个term,如果有成百上千个term呢,那找出某个term就会很慢,因为term还没有排序,解决这个问题需要了解两个概念:Term Dictionary 和 Term Index。

Term Dictionary
Elasticsearch为了能快速找到某个term,将所有的term进行了排序,然后二分法查找term,类似于上学时候老师教我们的翻新华字典的方式,所以这叫做Term Dictionary,这种查询方式其实和传统关系型数据库的B-Tree的方式很相似,所以这并不是Elasticsearch快的原因。

Term Index
如果说Term Dictionary是直接去二分法翻字典,那么Term Index就是字典的目录页(当然这比我们真的去翻字典目录快多了),假设我们的term如果全是英文单词,那么Term Index就是26个字母表,但是通常term未必都是英文,而可以是任意的byte数组。因为就算26个英文字符也不一定都有对应的term,比如:a开头的term只有一个,c开头的term有一百万个,x开头的term一个也没有,这样查询到c的时候又会很慢了。所以通常情况下Term Index 是包含term的一些前缀的一棵树,例如这样的一个Term Index:
在这里插入图片描述
这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。
在这里插入图片描述

这样的情况下通过Term Index据可以快速定位到某个offset(分支的开端),然后以此位置向下查找,再加上FST(Finite-State Transducer,Lucene4.0开始使用该算法来查找Term 在Dictionary中的位置)的压缩技术,将Term Index 缓存到内存中,通过Term Index 找到对应的Term Dictionary的 block,然后再去磁盘直接找到term,减少磁盘的随机读写次数,大大的提升查询效率。


3、Posting List压缩技术 Roaring Bitmap

说到Roaring bitmaps,就必须先从bitmap说起。Bitmap是一种数据结构,假设有某个posting list:
[1,3,4,7,10]
对应的bitmap就是:
[1,0,1,1,0,0,1,0,0,1]

非常直观,用0/1表示某个值是否存在,比如10这个值就对应第10位,对应的bit值是1,这样用一个字节就可以代表8个文档id,旧版本(5.0之前)的Lucene就是用这样的方式来压缩的,但这样的压缩方式仍然不够高效,如果有1亿个文档,那么需要12.5MB的存储空间,这仅仅是对应一个索引字段(我们往往会有很多个索引字段)。于是有人想出了Roaring bitmaps这样更高效的数据结构。


Bitmap的缺点是存储空间随着文档个数线性增长,Roaring bitmaps需要打破这个魔咒就一定要用到某些指数特性:

Elasticsearch不仅压缩了Term Index,还对posting list 进行了压缩,posting list虽然只存储了文档id,但是当文档id很大的时候,比PB级的数据,Elasticsearch对posting list的压缩做了两件事:排序和大数变小数,引用一张被引用无数次的图:
在这里插入图片描述

解释上面的图:
step1:在对posting list进行压缩时进行了正序排序。
step2:通过增量将73后面的大数变成小数存储增量值。
step3: 转换成二进制,取占最大位的数,227占8位,前三个占八位,30占五位,后三个数每个占五位。


上面的step3中可以看出,这种压缩方式仍然不够高效,所以Lucene使用的数据结构叫做Roaring Bitmap,其压缩的原理可以理解为,与其保存100个0,占用100个bit,还不如保存0一次,然后声明这个0有100个,它以两个自己可以表示的最大数65535为界,将posting list分块,比如第一块是0-65535,第二块是65536-131071,如图:
在这里插入图片描述
解释上面的图:
step1:从小到大进行排序。
step2:将大数除以65536,用除得的结果和余数来表示这个大数。
step3::以65535为界进行分块。


为什么是以65535为界限?
程序员的世界里除了1024外,65535也是一个经典值,因为它=2^16-1,正好是用2个字节能表示的最大数,一个 short[] 的存储单位,注意到上图里的最后一行“If a block has more than 4096 values, encode as a bit set, and otherwise as a simple array using 2 bytes per value(如果一个块有超过4096个值,则编码为一个位集,否则编码为一个简单数组,每个值使用2个字节)”。

为什么用4096来区分大块还是小块呢?
4096*2bytes = 8192bytes < 1KB, 磁盘一次寻道可以顺序把一个小块的内容都读出来,再大一位就超过1KB了,需要两次读。


4、联合索引

上面说了半天都是单field索引,如果多个field索引的联合查询,倒排索引如何满足快速查询的要求呢?

利用跳表(Skip list)的数据结构快速做“与”运算,或者利用上面提到的bitset按位“与”

先看看跳表的数据结构:

下面是一个链表的数据结构:
在这里插入图片描述
从链表中搜索(32,39,77)需要查找的次数为:2+4+6 =12次,可以得到所有结果,这样做其实没有用到链表的有序性,我们在查询39,77时候其实都做了一些重复查找,势必会造成效率低的问题,这时候可以用Skip List算法来优化查找次数,把某些节点提取出来,将链表分成两级:
在这里插入图片描述
样我们在查找39,77的时候次数就得到了简化,因为列表时有序的,所以当我们查到15的时候,23的大概位置就知道了(15—>23),查到31的时候,39的大概位置也就知道了(15—>31—>39),查到72的时候,77的大概位置也就知道了(15—>31—>72—>77)。避免了一部分重复查查找,这时候我们找到所以结果的次数为2+3+4 = 9次,查询77的时候似乎又对39的查找重复了一次,似乎还有优化的空间,那我们再对二级链表再进行一次分级:
在这里插入图片描述

样我们在查找77的时候次数就得到了简化,因为列表时有序的,所以当我们查到15的时候,23的大概位置就知道了(15—>23),查到31的时候,39的大概位置也就知道了(15—>31—>39),查到72的时候,77的大概位置也就知道了(15—>72—>77)。避免了一部分重复查查找,这时候我们找到所以结果的次数为2+3+3 = 8次。

从Skip List的查找原理可以看出,它的高效其实是牺牲了一定的空间冗余换来的,所以在有些情况下还是使用bitset更加的直观,比如下面这种数据结构:

level031572
level0215317290
level0115233139727790

五、IK 分词器

1、简介

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作 ,默认的中文分词是将每个字看成一个词,比如“我爱寒江”会被分为"我",“爱”,“寒”,“江” ,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。

如果要使用中文,建议使用ik分词器!

IK提供了两个分词算法: ik_ smart和ik_ max _word ,其中ik. smart为最少切分, ik max word为最细粒度划分! -会我们测试!

2、安装

下载

下载地址: https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.6.1
在这里插入图片描述

解压

解压到 elasticsearch-7.6.1\plugins \ik下
在这里插入图片描述

重启elasticsearch

我们可以发现analysis-ik分词器插件已经被加载了。
在这里插入图片描述

3、使用Kibana实现分词

简单测试

开启elasticsearch和Kibana,访问http://localhost:5601/.IK提供了两个分词算法: ik_ smart和ik_ max _word,我们下面就来试一试这两种方式的区别。

我们可以发现,我们使用ik_smart时,只是进行简单的分词处理,如下:
在这里插入图片描述

我们可以发现,当我们使用ik_max_word时,时进行复杂的分词处理,就就是更细致换的分词,如下:
在这里插入图片描述

自定义词库

我们还可能遇到这么一种情况,就是当字典中没有我们需要的词时,那么它就不会将我们需要词进行分词处理。

例如:我们的名字是胡学好,但是字典中并没有我的名字,所以默认并不会将我的名字进行分词。
在这里插入图片描述

我们需要将我们需要的词加入到elasticsearch的字典中。操作如下:

打开这个文件
在这里插入图片描述在这里插入图片描述

编写自己的字典
在这里插入图片描述
在这里插入图片描述

配置自定义的字典的路径
在这里插入图片描述
重启elasticsearch,并重新测试
在这里插入图片描述

六、Rest 风格测试

一种软件架构风格 ,而不是标准,只是提供了一-组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

我们的操作都是通过Kibana进行操作的。

1、elasticsearch的Rest操作

在这里插入图片描述
创建一个索引为studioustiger,类型名称为type1,id为1的文档
在这里插入图片描述
打开 head ,访问http://localhost:9200/,我们可以发现我们创建的文档已经被head捕捉到了,而且是一条记录的形式被捕捉到的,类似于关系型数据库。
在这里插入图片描述

2、ElasticSearch 字段类型

在这里插入图片描述

创建一个索引,指定其字段类型。我们在创建索引的时候,只需要指定索引名称即可。(格式固定)
在这里插入图片描述
我们可以发现,我们创建的只是单纯的索引,并没有值,但是字段的类型已经被指定好了。
在这里插入图片描述
elasticsearch是很智能的,即使我们不指定数据类型,那么elasticsearch会自定比配

3、增(插入)

在这里插入图片描述
在这里插入图片描述

4、删(删除)

在这里插入图片描述

5、改(修改)

在这里插入图片描述

6、查(查询)

q=:query表示查询。
name:zhangsan:表示的是精准查询,只有name值完全等于zhangsan时才会被查出。多个条件之间使用&连接
在这里插入图片描述

我们可以发现,如果只是匹配zhang,那么是查不出来的。
在这里插入图片描述

七、复杂搜索(☆☆☆)

1、组合查询

在mysql中,我们知道我们是可以进行复杂查询的,例如(模糊、排序、分页…),在elasticsearch中也是支持复杂查询的。

要查询的索引如下:
在这里插入图片描述


query:表示查询

match_phrase_prefix:表示前缀匹配
match_all:查询所有
match:表示模糊匹配(只有ik分词器可以分出来的词时可以被模糊查询到的)

_source:表示要查询那些字段(和sql中的select xxx, xxxx 效果相同)

sort:表示排序(desc是降序,asc是升序)

from x ,size x:表示分页(索引是从0开始的)

GET /tiger/_search
{
  "query": {
    "match": {
      "name": "胡学好"
    }
  },
  "_source": ["name","age"],
  "sort": [
    {
      "age": {
        "order": "asc"
      }
    }
  ],
  "from": 0,
  "size": 3
}

在这里插入图片描述

我们可以查询所有信息,那么可以使用"match_all": {}

GET /tiger/_search
{
  "query": {
    "match_all": {}  //表示查询所有信息
  }
}

2、条件查询

must_not

查询的结果不能包含 must_not 中任意一个条件,如下:查询的结果中的age不能是42 或 name中不能带03的记录

GET /tiger/_search
{
  "query": {    
    "bool": {	 
      "must_not": [	
        {
          "match": {
            "age": 42
          }
        },
        {
          "match": {
            "name": "03"
          }
        }
      ]
    }
  }
}

在这里插入图片描述

must

查询的结果中必须满足must中的所有条件,如下:查询的结果中的每一条记录中的name必须等于“胡学好”,age必须等于333

GET /tiger/_search
{
  "query": {
    "bool": {
      "must": [  //表示满足如下所有条件的记录被查询出来
        {
          "match": {
          "name": "胡学好"
          }
        },
        {
          "match": {
          "age": 333
          }
        }
      ]
    }
  }
}

在这里插入图片描述

should

查询的结果中的记录只要满足should中的任意一个条件即可,如下:查询的结果中只要满足gender是woman,或age等于18即可

GET /tiger/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
          "gender": "woman"
          }
        },
        {
          "match": {
          "age": 18
          }
        }
      ]
    }
  }
}

在这里插入图片描述

3、查询结果过滤

对于查询的结果,我们可以只用filter进行过滤

GET /tiger/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
          "gender": "man"
          }
        }
      ],
      "filter": {   // 过滤查询的结果
        "range": {  //范围
          "age": {  // 过滤age的范围
            "gt": 14,   //大于14
            "lt": 100   //小于100
          }
        }
      }
    }
  }
}

在这里插入图片描述

4、term查询

term查询是通过倒排索引进行精确查询的,使用的是默认的分词器(standard)进行分词的,standard会将一段文本分解成一个一个的字,不会出现词组的情。match查询会使用ik分词器(先分析文档,然后通过分析的文档进行查询)

我们可以发现使用term进行查询"胡学好"时,没有查询结果,说明term没有使用ik分词器

GET /tiger/_search
{
  "query": {
    "term": {
      "name": "胡学好"
    }
  }
}

在这里插入图片描述

我们可以发现使用term进行查询"胡"时,有查询结果,说明term使用的是默认的分词器(standard)

GET /tiger/_search
{
  "query": {
    "term": {
      "name": "胡"
    }
  }
}

在这里插入图片描述

5、keyworld 类型

在elasticsearch中分词器会对类型为text的内容进行分词器解析,不会对类型为keyworld的内容进行分词器解析

如下我们创建了一个索引,并将name的类型置为keyword类型,插入了三条数据

PUT studious
{
  "mappings": {
    "properties": {
      "name":{
        "type": "keyword"
      }
    }
  }
}

PUT studious/_doc/1
{
  "name": "胡学好01"
}

PUT studious/_doc/2
{
  "name": "胡学好02"
}

PUT studious/_doc/3
{
  "name": "胡学好03"
}

使用match查询"胡学好",没有查询结果,说明keyworld不会被分词器解析

GET studious/_search
{
  "query": {
    "match": {
      "name": "胡学好"
    }
  }
}

在这里插入图片描述

使用match查询"胡学好01",有查询结果,说明我们只能进行精准查询

GET studious/_search
{
  "query": {
    "match": {
      "name": "胡学好01"
    }
  }
}

对于term查询,我们也可以使用多个值匹配的精确查询,如下

GET studious/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "name": "胡学好01"
          }
        },
        {
          "term": {
            "name": "胡学好02"
          }
        }
      ]
    }
  }
}

在这里插入图片描述

6、高亮查询

在一些电商网址站中,我们搜索一些商品时,对于商品的搜索信息会有一些高亮的显示,如下:
在这里插入图片描述

在elasticsearch中给我提供了高亮查询的操作,我们可以在"highlight": {}中自定义高亮设置。我们可以看到,高亮查询的结果中,指定的字段被加上的自定义HTML标签

GET tiger/_search
{
  "query": {
    "match": {
      "name": "胡好学"
    }
  },
  "highlight": {
    "pre_tags": "<em style='color:red'>",   //自定义前缀
    "post_tags": "</em>", 					//自定义后缀
    "fields": {
      "name": {}							//自定义显示高亮的字段
    }
  }
}

在这里插入图片描述

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值