分布式搜索ES

Elastic Search简介

什么是elasticsearch?

elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容

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

 

数据可视化

 

存储、搜索、分析数据

 

数据抓取

 

 

ElasticSearch的底层是Lucene技术(apache组织提供)

 

 

Elastic Search的发展

2004年Shay Banon基于Lucene开发了Compass

2010年Shay Banon重写了Compass,取名为Elasticsearch

官网地址:https://www.elastic.co/cn/

相比与Lucene,elasticsearch具备下列优势

 

较热门的搜索引擎技术:

 

倒排索引

正向索引和倒排索引

 

正向索引(根据文档找到词)

传统数据库(如mysql)采用正向索引,例如给下表(tb_goods)中的id创建索引:

idtitleprice
1小米手机3499
2华为手机4999
3华为小米充电器49
4小米手环49
.........

搜索 手机

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

逐条数据扫描,判断是否包含手机,如果包含则存入结果集中

 

 

倒排索引(根据词找文档)

词条(term)文档id
小米1,3,4
手机1,2
华为2,3
充电器3
手环4

elasticsearch采用倒排索引

 

使用倒排索引搜索华为手机

  1. 分词,得到华为手机两个词条

  2. 根据词条去词条列表查询文档id

  3. 得到每个词条所在文档id:

    华为:2,3

    手机:1,2

  4. 根据文档id查询文档,得到id为1,2,3的文档,存入结果集中(2的关联度较高会放在前面)

 

文档

elasticsearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息

文档数据会被序列化为JSON格式后存储在elasticsearch中

 

索引(Index)

相同类型的文档的集合,如商品索引,用户索引,订单索引(类似数据库表的概念)

 

映射(mapping):索引中文档的字段约束信息,类似表的结构约束

 

 

概念对比

MySQL Elasticsearch 说明
Table Index 索引(index),就是文档的集合,类似数据库的表(table)
Row Document 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式
Column Field 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)
Schema Mapping Mapping(映射)是索引中文档的约束,例如字段类型约束,类似数据库的表结构(Schema)
SQL DSL DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

 

架构对比

 

ES承担了搜索操作,Mysql承担了写操作,mysql可以将数据同步到ES中(起到了互补的效果)

 

安装ES

部署单点es

1、创建网络

因为我们还要部署kibana容器,因此需要让es和kibana容器互联,这里先创建一个网络:

 

2、加载镜像

这里我们采用elasticsearch的1.12.1版本的镜像,这个镜像体积非常大,接近1G,不建议自己pull

使用镜像tar包,上传到虚拟机使用命令加载即可

同理kibana的tar包也是如此

 

3、运行

运行docker命令,部署单点es:

-e参数说明

-v参数说明

--network : 加入网络

--privileged:授予逻辑卷访问权

-p参数说明

9200端口:http端口,提供用户访问

9300端口:容器之间各个节点互联端口

输入192.168.119.88:9200查看访问结果

 

部署Kibana

kibana版本需要和es版本保持一致

 

浏览器访问192.168.119.88:5601查看图形化界面

 

使用Kibana提供的Dev Tools来发送DSL语句(本质上就是发送一个RESTFUL的请求到es当中)

 

测试es是否连接

 

分词器

es在创建倒排索引时需要对文档分词,在搜索时,需要对用户输入内容分词,但默认的分词规则对中文处理并不友好,我们在kibana的DevTools中测试

语法说明:

POST:请求方式

/_analyze:请求路径,这里省略了http://192.168.119.88:9200,由kibana帮我们补充

请求参数,json风格:

 

IK分词器

 

安装分词器

处理中文分词,一般会使用IK分词器

网址:https://github.com/medcl/elasticsearch-analysis-ik

 

安装IK分词器

在线拉取

 

离线安装

安装插件需要知道elasticsearch的plugins目录位置,而我们用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过下面命令查看

显示结果:

说明plugins目录被挂载到了:/var/lib/docker/volumes/es-plugins/_data这个目录中

 

重启容器

 

测试IK分词器

IK分词器包含两种模式:

 

 

字典个性化设置

分词器都会依赖于一个字典来进行分词,我们可以为字典添加拓展词汇和停用词汇

 

ik分词器-拓展词库

要拓展ik分词器的词库,需要修改ik分词器目录下config目录中的IkAnalyzer.cfg.xml文件

 

 

指定拓展词所在文件名(与当前目录同级)

 

创建ext.dic,添加扩展词即可,一行一个词语,注意必须都是UTF-8编码格式

 

分词器的作用

 

 

索引库操作

mapping属性

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

 

创建索引库

ES中通过Restful请求操作索引库、文档,请求内容用DSL语句来表示

创建索引库和mapping的DSL语法如下:

 

创建索引库

 

查询、删除索引库

 

修改索引库

禁止修改原有字段

禁止修改索引库原有字段,因为mapping约束定义好后,es就会创建倒排索引库,如果修改原字段会对倒排索引库产生影响

 

添加新字段

索引库和mapping一旦创建无法修改,但可以添加新字段(新字段名不能和旧字段名重复

测试

 

 

文档操作

新增文档

每次写操作都会导致文档版本增加

DSL语法:

如果不加id,会由ES随机生成id

测试

 

查询文档

测试

 

删除文档

测试

 

修改文档

方式一:全量修改,会删除旧文档添加新文档(如果id不存在则新增)

测试

 

方式二:增量修改(局部修改),修改指定字段

测试

 

RestClient操作索引库

以后在java开发中,我们会使用java代码来实现操作es引擎,因此我们使用es官方提供的RestClient

 

什么是RestClient?

ES官方提供了各种不同语言的客户端,用来操作ES,这些客户端的本质就是组装DSL语句,通过http请求发送给ES

官方文档:https://www.elastic.co/guide/en/elasticsearch/client/index.html

 

利用JavaRestClient实现创建、删除索引库,判断索引库是否存在

 

mapping要考虑的问题:

字段名、数据类型、是否参与搜索、是否分词、如果分词,分词器是什么

 

ES中支持两种地理坐标数据类型:

 

字段拷贝

当我们需要对几个相关字段进行查询的时候,我们可以使用copy_to工具来高效的创建一个新的字段来存储我们需要查询的词

字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段,实例:

参考博客

 

 

示例

 

初始化JavaRestClient

引入es的RestHighLevelClient依赖坐标

 

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

 

初始化RestHighLevelClient

 

测试

 

Java索引库操作

创建索引库

步骤:

1、准备request对象,指定索引库名称

2、指定DSL,以及格式为JSON

3、获取到索引库操作对象,调用创建索引库的方法

测试

 

删除索引库

 

 

判断索引库是否存在

 

 

Java文档操作