ElasticSearch是什么
Elaticsearch简称为ES,是一个开源的可扩展的分布式的全文检索引擎,它可以近乎实时的存储、检索数据。本身扩展性很好,可扩展到上百台服务器,处理PB级别的数据。ES使用Java开发并使用Lucene作为其核心来实现索引和搜索的功能,但是它通过简单的RestfulAPI和javaAPI来隐藏Lucene的复杂性,从而让全文搜索变得简单。
PB是数据存储容量的单位,它等于2的50次方个字节,或者在数值上大约等于1000个TB。
Elasticsearch官网:https://www.elastic.co/cn/products/elasticsearch
ElasticSearch的功能
- 分布式的搜索引擎
- 分布式:Elasticsearch自动将海量数据分散到多台服务器上去存储和检索
- 搜索:百度、谷歌,站内搜索
- 全文检索
- 提供模糊搜索等自动度很高的查询方式,并进行相关性排名,高亮等功能
- 数据分析引擎(分组聚合)
- 电商网站,最近一周笔记本电脑这种商品销量排名top10的商家有哪些?新闻网站,最近1个月访问量排名top3的新闻板块是哪些
- 对海量数据进行近实时的处理
- 海量数据的处理:因为是分布式架构,Elasticsearch可以采用大量的服务器去存储和检索数据,自然而然就可以实现海量数据的处理
- 近实时:Elasticsearch可以实现秒级别的数据搜索和分析
ElasticSearch特点
Elasticsearch的特点是它提供了一个极速的搜索体验。这源于它的高速(speed)。相比较其它的一些大数据引擎,Elasticsearch可以实现秒级的搜索,速度非常有优势。Elasticsearch的cluster是一种分布式的部署,极易扩展(scale )这样很容易使它处理PB级的数据库容量。最重要的是Elasticsearch是它搜索的结果可以按照分数进行排序,它能提供我们最相关的搜索结果 (relevance)。
- 安装方便:没有其他依赖,下载后安装非常方便;只用修改几个参数就可以搭建起来一个集群
- JSON:输入/输出格式为 JSON,意味着不需要定义 Schema,快捷方便
- RESTful:基本所有操作 ( 索引、查询、甚至是配置 ) 都可以通过HTTP接口进行
- 分布式:节点对外表现对等(每个节点都可以用来做入口)加入节点自动负载均衡
- 多租户:可根据不同的用途分索引,可以同时操作多个索引
- 支持超大数据:可以扩展到PB级的结构化和非结构化数据,海量数据的近实时处理
主流全文搜索方案对比
- Lucene
- Lucene是Apache基金会维护的一套完全使用Java编写的信息搜索工具包(Jar包),它包含了索引结构、读写索引工具、相关性工具、排序等功能,因此在使用Lucene时仍需要我们自己进一步开 发搜索引擎系统,例如数据获取、解析、分词等方面的东西。 注意:Lucene只是一个框架,我们需要在Java程序中集成它再使用。而且需要很多的学习才能明白它是如何运行的,熟练运用Lucene非常复杂。
- Solr
- Solr是一个有HTTP接口的基于Lucene的查询服务器,是一个搜索引擎系统,封装了很多Lucene细 节,Solr可以直接利用HTTP GET/POST请求去查询,维护修改索引。
- Elasticsearch
- Elasticsearch也是一个建立在全文搜索引擎 Apache Lucene基础上的搜索引擎。采用的策略是分 布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
- 三者之间的区别和联系
- Solr和Elasticsearch都是基于Lucene实现的。
- Solr利用Zookpper进行分布式管理,而Elasticsearch自身带有分布式协调管理功能 - Solr比Elasticsearch实现更加全面,Solr官方提供的功能更多,而Elasticsearch本身更注重于 核心功能, 高级功能多由第三方插件提供
- Solr在传统的搜索应用中表现好于Elasticsearch,而Elasticsearch在实时搜索应用方面比Solr 表现好
ElasticSearch核心概念
- 索引(index)
- 类似的数据放在一个索引,非类似的数据放不同索引, 一个索引也可以理解成一个关系型数据 库。
- 类型(type)
- 代表document属于index中的哪个类别(type)也有一种说法一种type就像是数据库的表,比如dept表,user表。
- 注意ES每个大版本之间区别很大:
- ES 5.x中一个index可以有多种type。
- ES 6.x中一个index只能有一种type。
- ES 7.x以后 要逐渐移除type这个概念。
- ES 8.x以后 徹底移除type这个概念。
- 映射(mapping)
- mapping定义了每个字段的类型等信息。相当于关系型数据库中的表结构。 常用数据类型:text、keyword、number、array、range、boolean、date、geo_point、ip、 nested、object
- 官网解释地址
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html#_multi_fields_2
ElasticSearch API
Elasticsearch提供了Rest风格的API,即http请求接口,而且也提供了各种语言的客户端API。
- Rest风格API
- 文档地址:
https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
- 文档地址:
- 客户端API
- Elasticsearch支持的语言客户端非常多:
https://www.elastic.co/guide/en/elasticsearch/client/index.html
- Elasticsearch支持的语言客户端非常多:
ElasticSearch索引操作
创建
PUT /索引名称
{ "settings":
{
"属性名": "属性值"
}
}
settings:就是索引库设置,其中可以定义索引库的各种属性比如分片数副本数等,目前我们可以不设置,都走默认
查询
- 索引是否存在
HEAD /索引名称
- 查询单个索引
GET /索引名称
- 查询多个索引
GET /索引名称1,索引名称2,索引名称3,...
- 查看所有索引
- 方式一
GET _all
- 方式二
GET /_cat/indices?v
- health字段
- 绿色:索引的所有分片都正常分配。
- 黄色:至少有一个副本没有得到正确的分配。
- 红色:至少有一个主分片没有得到正确的分配。
删除
DELETE /索引名称1,索引名称2,索引名称3...
开关
- 打开索引
POST /索引名称/_open
- 关闭索引
POST /索引名称/_close
mapping映射操作
索引创建之后,等于有了关系型数据库中的database。Elasticsearch7.x取消了索引type类型的设置,不允许指定类型,默认为_doc,但字段仍然是有的,我们需要设置字段的约束信息,叫做字段映射(mapping)
字段的约束包括但不限于:
- 字段的数据类型
- 是否要存储
- 是否要索引
- 分词器
创建映射字段
PUT /索引库名/_mapping
{
"properties": {
"字段名": {
"type": "类型",
"index": true,
"store": true,
"analyzer": "分词器"
}
}
}
字段名:任意填写,下面指定许多属性,例如:
- type:类型,可以是text、long、short、date、integer、object等
- index:是否索引,默认为true
- store:是否存储,默认为false
- analyzer:指定分词器
映射属性详解
type
Elasticsearch中支持的数据类型非常丰富:
- String类型,又分两种:
- text:可分词,不可参与聚合
- keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合
- Numerical:数值类型,分两类
- 基本数据类型:long、interger、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
- Date:日期类型 elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省 空间。
- Array:数组类型
- 进行匹配时,任意一个元素满足,都认为满足
- 排序时,如果升序则用数组中的最小值来排序,如果降序则用数组中的最大值来排序
- Object:对象
{ name:"zs", param:{ age: 18, sex:"男" } }
如果存储到索引库的是对象类型,例如上面的param,会把param变成两个字段:param.age 和param.sex
index
index影响字段的索引情况。
- true:字段会被索引,则可以用来进行搜索。默认值就是true
- false:字段不会被索引,不能用来搜索
index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引。 但是有些字段是我们不希望被索引的,比如企业的logo图片地址,就需要手动设置index为false。
store
是否将数据进行独立存储。 原始的文本会存储在 _source 里面,默认情况下其他提取出来的字段都不是独立存储的,是从 _source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置store:true即可,获取独立存 储的字段要比从_source中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置, 默认为false。
analyzer
指定分词器 一般我们处理中文会选择ik分词器 ik_max_word ik_smart
查看映射关系
- 查看单个索引映射关系
GET /索引名称/_mapping
- 查看所有索引映射关系
- 方式一
GET _mapping - 方式二
GET _all/_mapping
- 方式一
- 修改索引映射关系
PUT /索引库名/_mapping
{
"properties": {
"字段名": {
"type": "类型",
"index": true,
"store": true,
"analyzer": "分词器"
}
}
}
注意:修改映射增加字段 做其它更改只能删除索引 重新建立映射
一次性创建索引和映射
在创建索引库的同时,直接制定索引库中的索引,基本语法:
put /索引库名称
{
"settings": {
"索引库属性名": "索引库属性值"
},
"mappings": {
"properties": {
"字段名": {
"映射属性名": "映射属性值"
}
}
}
}
文档增删改查及局部更新
文档,即索引库中的数据,会根据规则创建索引,将来用于搜索。可以类比做数据库中的一行数据。
新增文档
新增文档时,涉及到id的创建方式,手动指定或者自动生成。
- 新增文档(手动指定id)
POST /索引名称/_doc/{id}
{
"field": "value"
}
- 新增文档(自动生成id)
POST /索引名称/_doc
{
"field": "value"
}
示例:
可以看到结果显示为:created,代表创建成功。
另外,需要注意的是,在响应结果中有个_id字段,这个就是这条文档数据的唯一标识 ,以后的增删改查都依赖这个_id作为唯一标示,这里是Elasticsearch帮我们随机生成的id。
查看单个文档
GET /索引名称/_doc/{id}
示例:
返回内容解读:
| 元数据项 | 含义 |
|---|---|
| _index | document所属index |
| _id | 代表document的唯一标识,可以唯一标识和定位一个 document |
| _version | document的版本号,Elasticsearch利用_version (版本号)的方式来确保应用中相互冲突的变更不会导致数据丢失。需要修改数据时,需要指定想要修改文档的version号,如果该版本不是当前版本号,请求将会失败 |
| _seq_no | 严格递增的顺序号,每个文档一个,Shard级别严格递增,保证后写入的Doc seq_no大于先写入的Doc的seq_no |
| _primary_term | 任何类型的写操作,包括index、create、update和Delete,都会生成一个_seq_no。 |
| found | true/false,是否查找到文档 |
| _source | 存储原始文档 |
查看所有文档
POST /索引名称/_search
{
"query": {
"match_all": {}
}
}
_source定制返回结果
某些业务场景下,我们不需要搜索引擎返回source中的所有字段,可以使用source进行定制,如下,多 个字段之间使用逗号分隔
GET /索引/_doc/{id}?_source={field1},{field2}
更新文档(全部更新)
把刚才新增的请求方式改为PUT,就是修改了,不过修改必须指定id
- id对应文档存在,则修改
- id对应文档不存在,则新增
- 存在
显示的是updated - 不存在
显示的是created
更新文档(局部更新)
Elasticsearch可以使用PUT或者POST对文档进行更新(全部更新),如果指定ID的文档已经存在,则执行更新操作。
注意:Elasticsearch执行更新操作的时候,Elasticsearch首先将旧的文档标记为删除状态,然后添加新的文档,旧的文档不会立即消失,但是你也无法访问,Elasticsearch会在你继续添加更多数据的时候在 后台清理已经标记为删除状态的文档。
全部更新,是直接把之前的老数据,标记为删除状态,然后,再添加一条更新的(使用PUT或者POST)局域更新,只是修改某个字段(使用POST)
- 语法
POST /索引名/_update/{id}
{
"doc": {
"field": "value"
}
}
删除文档
- 根据id删除
DELETE /索引名/_doc/{id} - 更具查询条件删除
POST /索引库名/_delete_by_query
{
"query": {
"match": {
"字段名": "搜索关键字"
}
}
}
- 删除所有文档
POST 索引名/_delete_by_query
{
"query": {
"match_all": {}
}
}
文档的强制创建
- 强制创建
- 如果id存在就会报错
PUT /index/_doc/{id}?op_type=create {}PUT /index/_doc/{id}/_create {}