1.了解ES
1.1.elasticsearch的作用
elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容
例如:
在github上搜索项目
在电商网站搜索商品:
在百度搜索答案:
在打车软件搜索附近的车
1.2ELK技术栈
elasticsearch结合Kibana、Logstash、Beats,也就是elastic stack(ELK),被广泛应用在日志数据分析、实时监控等领域
而elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。
1.2.elasticsearch和lucene
elasticsearch底层是基于LUCENE来实现的
LUCENE是一个java语言的搜索引擎是Apache公司的顶级项目,由DougCutting于1999年研发,官网地址https://lucene.apache.org/
Lucene的优势:
易扩展
高性能
Lucene的缺点:
只限于Java语言开发
学习曲线陡峭
不支持水平发展
目前比较知名的搜索引擎技术排名:
虽然在早期,Apache Solr是最主要的搜索引擎技术,但随着发展elasticsearch已经渐渐超越了Solr,独占鳌头:
总结
什么是elasticsearch?
- 一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能
什么是elastic stack(ELK)? - 是以elasticsearch为核心的技术栈,包括beats、Logstash、kibana、elasticsearch
什么是Lucene? - 是Apache的开源搜索引擎类库,提供了搜索引擎的核心API
2.倒排索引
倒排索引的概念是基于Mysql这样的正向索引而言的。
2.1正向索引
那么什么是正向索引呢?例如给下表的(tb_goods)中的id创建索引:
如果是根据id查询,那么直接走索引,查询速度非常快。
但如果是基于title做模糊查询,只能逐行扫描数据,流程如下:
1)用户搜索数据,条件是title符合"%手机%"
2)逐行获取数据,比如id为1的数据
3)判断数据中的title是否符合用户搜索条件
4)如果符合则放入结果集,不符合则丢弃。回到步骤1
逐行扫描,也就是全表扫描,随着数据量增加,其查询效率会越来越低,当数据量达到数百万时,就是一场灾难
2.2倒排索引
倒排索引中有两个非常重要的概念:
文档(document):用来搜索的数据,其中每一条数据就是一个文档,例如一个网页,一个商品信息
词条(Term):对文档数据或用户搜索数据,利用某种算法分析,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国。国人这样的几个词条
创建倒排索引是对正向索引的一种特殊处理,流程如下:
将每一个文档的数据利用算法分词,得到一个个词条
创建表,每行数据包括词条,词条所在文档id,位置等信息
因为词条的唯一性,可以给词条创建索引,例如hash表结构索引
如图:
倒排索引的流程如下(以搜索华为手机为例):
1)用户输入条件华为手机进行搜索
2)对用户输入内容分词,得到词条:华为,手机
3)拿着词条在倒排索引中查找,可以得到包含词条的文档id:1、2、3
4)拿着文档的id到正向索引中查找具体文档
如图:
虽然要先查询倒排索引,再查询正向索引,但是无论是词条,还是文档文档id都建立了索引,查询速度非常快,无需全表扫描
2.3正向和倒排
那么为什么一个叫做吧正向索引,一个叫倒排索引呢?
正向索引是最传统的,根据id索引的方式,但根据词条查询时,必须先纸条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程
而倒排索引则相反,是先找到用户搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档,是根据词条找文档的过程
是不是恰好反过来了?
正向索引
优点:
可以给多个字段创建索引
根据索引字段搜索,排序速度非常快
缺点:
根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描
倒排索引:
优点:
根据词条搜索,模糊搜索时,速度非常快
缺点:
只能给词条创建索引,而不是字段
无法根据字段做排序
3.es的一些概念
elasticsearch中有很多独有的概念,与mysql中略有差别,但也有相似之处
3.1文档和字段
elasticsearch是面向文档(document)存储的,可以是数据库中的一条商品数据,一个订单信息,文当数据会被序列化为json格式后存储在elasticsearch中:
而Json文档中往往包含很多的字段(Field),类似于数据库中的列。
3.2.索引和映射
索引(Index),就是相同类型的文档的集合。
例如:
- 所有用户文档,就可以组织在一起,称为用户的索引;
- 所有商品的文档,可以组织在一起,称为商品的索引;
- 所有订单的文档,可以组织在一起,称为订单的索引
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 |
是不是说,我们学习了elasticsearch就不再需要mysql了呢?
并不是如此,两者各自有自己的擅长支出:
Mysql:擅长事务类型的操作,可以确保数据的安全和一致性
Elasticsearch:擅长海量数据的搜索、分析、计算
因此在企业中,往往是两者结合使用:
对安全要求较高的写操作,使用mysql实现
对查询性能要求较高的搜索需求,使用elasticsearch实现
两者再基于某种方式,实现数据的同步,保证一致性
3.3总结
分词器的作用是什么?
创建倒排索引时对文档分词
用户搜索时对输入的内容分词
IK分词器有几种模式?
ik_smart:智能切分,粗粒度
ik_max_word:最细切分,细粒度
IK分词器如何拓展词条?如何停用词条?
利用config目录的IKAnalyzer.cfg.xml文件添加拓展词典和停用词典
在词典中添加拓展词条或者停用词条
4.索引库操作
索引库就类似数据库表,mapping映射就类似表的结构
我们要向es中存储数据,必须先创建库和表
4.1mapping映射属性
mapping是索引库中的文档的约束,常见的mapping属性包括:
type:字段数据类型,常见的简单类型:
字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家。IP地址)
数值:long、integer、short、byte、double、float、
布尔:boolean
日期:date
对象:object
index:是否创建索引,默认为true
analyzer:使用那种分词器
properties:该字段的子字段
例如下面的json文档:
{
"age": 21,
"weight": 52.1,
"isMarried": false,
"info": "xxxxxxx",
"email": "xxxxxx.cn",
"score": [99.1, 99.5, 98.9],
"name": {
"firstName": "云",
"lastName": "赵"
}
}
对应的每个字段映射(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;无需分词器