一、elasticsearch的概述
elasticsearch
是一款非常强大的开源搜索引擎,底层是基于lucene
来实现的。具备非常多强大功能。
可以帮助用户从海量数据中快速找到需要的内容,是一个海量数据搜索技术。
elasticsearch通常会结合以下几个组件来配置使用:
即:kibana
、Logstash
、Beats
。
这三个组件加上elasticsearch
本身,被称为elastic stack
(ELK
),即elastic
技术栈的意思。
elastic stack
以elasticsearch
为核心被广泛应用在日志数据分析、实时监控等领域。
elastic stack的各组件作用:
-
kibana
:数据可视化 -
elasticsearch
:存储、计算、搜索数据 -
Logstash
、Beats
:数据抓取
elasticsearch的优势:
- 支持分布式,可水平扩展
- 提供
Restful
接口,可被任何语言调用
二、elasticsearch中的包含的基础概念
2.1 文档和字段
elasticsearch
是面向**文档(Document)**存储的。
文档是数据库中一条数据,文档数据会被序列化为json
格式后存储在elasticsearch
中。
而Json
文档中包含了很多的字段(Field),类似于数据库中的列。
2.2 索引和映射
索引(Index):相同类型的文档的集合。
例如:所有用户文档,就可以组织在一起,称为用户的索引。
因此,可以把索引当做数据库中的表。数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。
因此,索引库中就有映射(mapping),映射是索引中文档的字段约束信息,类似表的结构约束。
三、mysql和elasticsearch对比
3.1 基础概念对比
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 |
两者各自的优势:
-
mysql
:擅长事务类型操作,可以确保数据的安全和一致性 -
elasticsearch
:擅长海量数据的搜索、分析、计算
因此在企业中,往往是两者结合使用:
- 对安全性要求较高的写操作,使用
MySQL
实现 - 对查询性能要求较高的搜索需求,使用
elasticsearch
实现 - 两者再基于某种方式,实现数据的同步,保证一致性
3.2 正排索引和倒序索引
倒排索引的概念是基于MySQL
这样的正向索引而言的。
2.1 MySQL中的正排索引
正向索引可以简称为索引。正向索引是以关键字为主码,查询时需要遍历每一个文件。
每个文件都对应一个文件ID
,文件内容被表示为一串关键词的集合。
具体的来说就是根据id查询,那么直接走索引,查询速度非常快。
但如果是做模糊查询,就只能逐行扫描数据,当数据量超过百万时,查询效率将会非常的低。
2.2 elasticsearch中的倒排索引
1)倒排索引的两个重要概念:
-
文档(
Document
):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息 -
词条(
Term
):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。例如:我是中国人,就可以分为:我、是、中国人、中国、国人这样的几个词条。
2)倒排索引创建流程:
- 将每一个文档的数据利用算法分词,得到一个个词条
- 创建表,每行数据包括词条、词条所在文档id、位置等信息
- 因为词条唯一性,可以给词条创建索引,例如hash表结构索引
倒排索引是对正向索引的一种特殊处理
3)倒排索引搜索流程:
-
用户输入条件进行搜索。
-
对用户输入内容分词,得到词条。
-
拿着词条在倒排索引中查找,可以得到包含词条的文档id。
-
拿着文档id到正向索引中查找具体文档。
虽然要先查询倒排索引,再查询正排索引。
但是无论是词条、还是文档id都建立了索引,查询速度非常快!并且无需全表扫描。
2.3 正排索引和倒排索引的区别
-
正向索引是传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。
-
而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程。
2.4 正排索引和倒排索引的优缺点
正排索引:
-
优点:
可以给多个字段创建索引
根据索引字段搜索、排序速度非常快
-
缺点:
根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。
倒排索引:
-
优点:
根据词条搜索、模糊搜索时,速度非常快
-
缺点:
只能给词条创建索引,而不是字段
无法根据字段做排序
四、elasticsearch索引库操作
索引库就类似数据库表,mapping
映射就类似表的结构。
要向elasticsearch
中存储数据,必须先创建“库”和“表”。
4.1 mapping映射属性
mapping
是对索引库中文档的约束,即表结构的统称!
常见的mapping
属性包括:
-
type
:字段数据类型,常见的简单类型有:- 字符串:
text
(可分词的文本)keyword
(精确值:不可分词的文本,例如:品牌、国家、ip
地址)
- 数值:
long
、integer
、short
、byte
、double
、float
- 布尔:
boolean
- 日期:
date
- 对象:
object
- 地理位置:
geo_point
(使用逗号分隔存储的经纬度,在定位和搜索附件等功能时非常实用)
elasticsearch中是没有数组类型的,但是允许一个类型有多个值
所以integer类型可以写成:[1, 2, 3]
- 字符串:
-
index
:是否创建(倒排)索引,默认为true
-
analyzer
:使用哪种分词器 -
properties
:该字段的子字段 -
copy_to
:将当前字段拷贝到指定字段
text和keyword详解:
-
text
:字段类型是text
(并且需要创建索引)则分词器生效,会对内容进行分词,先分词然后把分词结果放入倒排索引
-
keyword
:如果一个字段类型是keyword
(并且需要创建索引),这个字段不分词原样存储到倒排索引
这些是常见的属性,并不是所有的,但足以应对大多数情况。
4.2 创建索引库和索引库中的映射
基本语法:
- 请求方式:
PUT
- 请求路径:/索引库名称(可以自定义)
- 请求参数:
mapping
映射
格式示例:
PUT /myfirst
{
"mappings": {
"properties": {
"address":{
"type": "text",
"analyzer": "ik_smart"
},
"email":{
"type": "keyword",
"index": false
},
"name":{
"type": "object",
"properties": {
"firstName": {
"type": "keyword"
},
"lastName": {
"type": "keyword"
}
}
}
}
}
}
对应的每个字段映射(mapping
)解析:
-
address
:类型为字符串,需要分词,因此是text
;要参与搜索,因此需要
index
为true
;分词器为用ik_smart
,因为默认分词器无法对中文分词 -
email
:类型为字符串,但是不需要分词,因此是数据类型是keyword
,且无需分词器;不参与搜索,无需创建倒排索引,因此需要
index
为false
-
name
:类型为object
,需要定义多个子属性-
name.firstName
;类型为字符串,但是不需要分词,因此数据类型是keyword
;需要参与搜索,因此需要创建倒排索引,
index
为true
;但是无需分词器 -
name.lastName
;类型为字符串,但是不需要分词,因此数据类型是keyword
;参与搜索,因此需要创建倒排索引,
index
为true
;但是无需分词器
-
copy_to的使用:
PUT /copyto
{
"mappings": {
"properties": {
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword",
"copy_to": "all"
},
"all":{
"type": "text",
"copy_to": "ik_max_word"
},
}
}
}
上面相当于把brand
字段和city
字段合并到all
字段中去。这样就能实现在一个字段中搜索到多个字段的内容。
并且这个合并已经做过优化,并不是直接把各个字段文档值给拷贝到all
字段中去。
而是基于all
创建倒排索引,所以查询的时候可能看不到all
字段,但是搜索的时候却可以根据它来搜索。
这样使用java api
查询的时候,可以直接查询all
字段,而不用一个个去查询其它字段。
4.3 查询索引库
基本语法:
-
请求方式:
GET
-
请求路径:/索引库名称
-
请求参数:无
格式示例:
GET /索引库名称
比如要查询上面新增的索引库:
GET /myfirst
4.4 删除索引库
语法:
-
请求方式:
DELETE
-
请求路径:/索引库名称
-
请求参数:无
格式:
DELETE /索引库名称
比如要删除上面新增的索引库:
DELETE /myfirst
4.5 修改索引库
倒排索引结构虽然不复杂,但是一旦数据结构改变,就需要重新创建倒排索引,这几乎是灾难。
因此在elasticsearch
当中,索引库一旦创建,无法再去修改其中的mapping结构。
虽然无法修改mapping
中已有的字段,但是允许添加新的字段到mapping
中,因为不会对倒排索引产生影响。
语法格式:
PUT /索引库名/_mapping
{
"properties": {
"新字段名":{
"type": "integer"
}
}
}
示例:
PUT /myfirst/_mapping
{
"properties": {
"age":{
"type": "integer"
}
}
}
_mapping是固定写法
新字段名不能和旧字段名一致,这会让elasticsearch认为你在更新索引库,会直接报错
五、elasticsearch文档操作
5.1 新增文档
语法格式:
POST /索引库名/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
"字段3": {
"子属性1": "值3",
"子属性2": "值4"
},
// ...
}
语法示例:
POST /myfirst/_doc/1
{
"info": "Java开发工程师",
"email": "123456789@qq.com",
"name": {
"firstName": "张",
"lastName": "肥聪"
}
}
_doc是固定写法
索引库id最好要加,要不然会随机生成一个
5.2 查询文档
根据rest
风格,新增是post
,查询应该是get
,不过查询一般都需要条件,需要把文档id
带上。
语法格式:
GET /索引库名称/_doc/{id}
语法示例:
GET /myfirst/_doc/1
5.3 批量查询文档
GET /hotel/_search
其实就是查询全部的
DSL
语句
5.4 删除文档
删除使用DELETE
请求,同样,需要根据id
进行删除:
语法格式:
DELETE /索引库名称/_doc/id值
语法示例:
// 根据id删除数据
DELETE /myfirst/_doc/1
5.5.修改文档
修改有两种方式:
- 全量修改:直接覆盖原来的文档
- 增量修改:修改文档中的部分字段
5.5.1 全量修改
全量修改是覆盖原来的文档,其本质是:
- 根据指定的
id
删除文档 - 新增一个相同
id
的文档
注意:如果根据id
删除时,id
不存在,第二步的新增也会执行,也就从修改变成了新增操作了。
语法格式:
PUT /索引库名称/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
// ... 略
}
语法示例:
PUT /myfirst/_doc/1
{
"info": "Java开发工程师",
"email": "978645312@qq.com",
"name": {
"firstName": "张",
"lastName": "三疯"
}
}
5.5.2 增量修改
增量修改是只修改指定id匹配的文档中的部分字段。
语法格式:
POST /索引库名称/_doc/文档id
{
"doc": {
"字段名": "新的值",
}
}
语法示例:
POST /heima/_update/1
{
"doc": {
"email": "978645312@qq.com"
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116466.html