Elasticsearch基础及使用

286 阅读11分钟

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)。

  1. 安装方便:没有其他依赖,下载后安装非常方便;只用修改几个参数就可以搭建起来一个集群
  2. JSON:输入/输出格式为 JSON,意味着不需要定义 Schema,快捷方便
  3. RESTful:基本所有操作 ( 索引、查询、甚至是配置 ) 都可以通过HTTP接口进行
  4. 分布式:节点对外表现对等(每个节点都可以用来做入口)加入节点自动负载均衡
  5. 多租户:可根据不同的用途分索引,可以同时操作多个索引
  6. 支持超大数据:可以扩展到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

image.png

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索引操作

创建

PUT /索引名称 
{ "settings": 
    { 
        "属性名": "属性值" 
    } 
}

settings:就是索引库设置,其中可以定义索引库的各种属性比如分片数副本数等,目前我们可以不设置,都走默认

查询

  • 索引是否存在
HEAD /索引名称
  • 查询单个索引
GET /索引名称
  • 查询多个索引
GET /索引名称1,索引名称2,索引名称3,...
  • 查看所有索引
  1. 方式一
GET _all
  1. 方式二
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中支持的数据类型非常丰富:

image.png

  • 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"
}

示例:

image.png 可以看到结果显示为:created,代表创建成功。 另外,需要注意的是,在响应结果中有个_id字段,这个就是这条文档数据的唯一标识 ,以后的增删改查都依赖这个_id作为唯一标示,这里是Elasticsearch帮我们随机生成的id。

查看单个文档

GET /索引名称/_doc/{id}

示例: image.png 返回内容解读:

元数据项含义
_indexdocument所属index
_id代表document的唯一标识,可以唯一标识和定位一个 document
_versiondocument的版本号,Elasticsearch利用_version (版本号)的方式来确保应用中相互冲突的变更不会导致数据丢失。需要修改数据时,需要指定想要修改文档的version号,如果该版本不是当前版本号,请求将会失败
_seq_no严格递增的顺序号,每个文档一个,Shard级别严格递增,保证后写入的Doc seq_no大于先写入的Doc的seq_no
_primary_term任何类型的写操作,包括index、create、update和Delete,都会生成一个_seq_no。
foundtrue/false,是否查找到文档
_source存储原始文档

查看所有文档

POST /索引名称/_search
{
  "query": {
    "match_all": {}
  }
}

_source定制返回结果

某些业务场景下,我们不需要搜索引擎返回source中的所有字段,可以使用source进行定制,如下,多 个字段之间使用逗号分隔

GET /索引/_doc/{id}?_source={field1},{field2}

更新文档(全部更新)

把刚才新增的请求方式改为PUT,就是修改了,不过修改必须指定id

  • id对应文档存在,则修改
  • id对应文档不存在,则新增
  1. 存在显示的是updated image.png
  2. 不存在显示的是created image.png

更新文档(局部更新)

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存在就会报错
    1. PUT /index/_doc/{id}?op_type=create {}
    2. PUT /index/_doc/{id}/_create {}