首页 > 其他分享 >Elasticsearch笔记

Elasticsearch笔记

时间:2024-08-03 22:55:01浏览次数:15  
标签:笔记 查询 索引 文档 分片 Elasticsearch 节点 集群

ES黑马课程笔记

课程:尚硅谷ElasticSearch教程入门到精通(基于ELK技术栈elasticsearch 7.x+8.x新特性
资料:百度网盘
课程评价:
官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 魔法

1 初识 ES

ES 简介

ES 是一个开源的高扩展的分布式全文搜索引擎(基于Lucene),可以用来实现搜索、日志统计、分析、系统监控等功能,是整个 Elastic Stack 技术栈的核心。
The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。

全文搜索引擎的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。

正向索引和倒排索引

正向索引:基于文档 id 创建索引。查询词条时必须先找到文档,而后判断是否包含词条
倒排索引:对文档内容分词,对词条创建索引,并记录词条所在文档的信息。查询时先根据词条查询到文档 id,而后获取到文档

MYSQL概念对比

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 安装

安装elasticsearch

Windows 下
直接官网下载解压即可。
进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务
打开浏览器,访问地址: http://localhost:9200

[!tip]
9300 端口为 Elasticsearch 集群间组件的通信端口
9200 端口为浏览器访问的 Http 协议 RESTful 端口

2 基本CRUD

索引库就类似 Mysql 中的表,mapping 映射就类似表的结构。我们要向 es 中存储数据,必须先创建“库”和“表”。

2.1 mapping 映射属性

mapping 是对索引库中文档的约束,具体请看官网: Mapping | Elasticsearch Guide 8.11,常见的 mapping 属性包括:

  • type:字段数据类型,常见的简单类型有:
    • 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip 地址)
    • 数值:long、integer、short、byte、double、float、
    • 布尔:boolean
    • 日期:date
    • 对象:object
  • index:是否创建索引,默认为 true
  • analyzer:使用哪种分词器
  • properties:该字段的子字段

2.2 索引库的 CRUD

这里我们统一使用 Kibana 编写 DSL 的方式来演示。

  • 创建索引库:PUT /索引库名 ,参数:mapping 映射
PUT /test_index2
{
  "mappings":{
    "properties":{
      "id": {
        "type": "long"
      },
      "userName": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "email": {
        "type": "keyword"
      },
      "profile": { 
        "properties":{
          "height": {
            "type": "double"
          },
          "weight": {
            "type": "double"
          }
        }
      }
    }
  }
}
  • 查询索引库:GET /索引库名,参数:无,如:GET /test_index
  • 删除索引库:DELETE /索引库名,参数:无,如:DELETE /test_index
  • 添加字段:PUT /索引库名/_mapping,参数:待添加字段的 mapping 映射
PUt /test_index/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

2.3 文档的 CRUD

  1. 创建文档:PUT /索引库名/_doc/id ,参数:文档值 json

    POST /test_index/_doc/1
    {
      "userName": "licw",
      "age": 18,
      "email": "[email protected]",
      "profile": {
          "height": 1.70,
          "weight": 51.4
        }
      }
    }
    
  2. 查询文档:GET /索引库名称/_doc/id,如:GET /test_index/_doc/1

  3. 删除文档:DELETE /索引库名/_doc/id ,如:DELETE /test_index/_doc/1

  4. 修改文档
    全量修改:直接覆盖原来的文档,本质是先根据 id 删除再新增相同 id 的文档,PUT /索引库名/_doc/id,参数同新增

增量修改POST /索引库名/_update/id {"doc":{文档数据}} 修改指定 id 匹配的文档中的部分字段。

POST /test_index/_update/1
{
  "doc": {
    "userName": "licw2"
  }
}

2.4 Java 操作基本 CURD

  1. Java Client :版本 7.16 ~ lastest,官网有相应的 java doc。
  2. Java REST Client :版本 5.0 ~ 7.17,直接看官网就可,挺清晰。
    黑马使用的 Java Rest Client 操作 ES 的案例:黑马 ES DAY 01
    官方文档截图

3 DSL 查询文档(数据搜索)

Elasticsearch 提供了基于 JSON 的 DSL(Domain Specific Language) 来定义查询。

3.1 查询类型

查询所有:查询出所有数据,一般测试用。例如:match_all

全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:match_querymulti_match_query

精确查询:根据精确词条值查找数据,一般是查找 keyword、数值、日期、boolean 等类型字段。例如:idsrangeterm

地理(geo)查询:根据经纬度查询。例如:geo_distancegeo_bounding_box

复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:boolfunction_score

3.2 查询语法

查询语法基本一致,具体的看 DSL 官方文档即可:

GET /indexName/_search  
{  
  "query": {  
    "查询类型": {  
      "查询条件": "条件值"  
    }  
  }  
}

复合查询讲解:

  1. function_score 查询
    语法分析image-20210721191544750
    function score 查询中包含四部分内容:
    原始查询:query 部分,基于这个条件搜索文档,并且基于 BM25算法给文档打分,得到原始算分(query score)
    过滤条件:filter部分,符合该条件的文档才会重新算分
    算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数

    • weight:函数结果是常量
    • field_value_factor:以文档中的某个字段值作为函数结果
    • random_score:以随机数作为函数结果
    • script_score:自定义算分函数算法
      运算模式:函数算分和原始算分之间的运算方式,包括:
    • multiply:相乘
    • replace:用function score替换query score
    • 其它,例如:sum、avg、max、min
      function score的运行流程如下:
    1. 根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)
    2. 根据过滤条件,过滤文档
    3. 符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)
    4. 原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分。
  2. bool 查询
    布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。子查询的组合方式有:

  • must:必须匹配每个子查询,类似“与”
  • should:选择性匹配子查询,类似“或”
  • must_not:必须不匹配,不参与算分,类似“非”
  • filter:必须匹配,不参与算分

[!tip]
需要注意的是,搜索时,参与打分的字段越多,查询的性能也越差。因此这种多条件查询时,建议这样做:
搜索框的关键字搜索,是全文检索查询,使用 must 查询,参与算分

其它过滤条件,采用 filter 查询。不参与算分

3.3 搜索结果处理

查询的 DSL 是一个大的 JSON 对象,包含查询条件、分页条件、排序条件、高亮条件四部分
image-20210721203657850

3.3.1 排序

keyword、数值、日期类型排序的语法基本一致。

GET /indexName/_search
{
  "query": {"match_all": {}},
  //排序条件数组
  "sort": [
    {
      "FIELD": "desc"  // 排序字段、排序方式ASC、DESC
    }
  ]
}

地理坐标排序(每一个文档中指定字段到目标点的距离排序)

GET /indexName/_search
{
  "query": {"match_all": {}},
  "sort": [
    {
      "_geo_distance" : {
          "FIELD" : "纬度,经度", // 文档中geo_point类型的字段名、目标坐标点
          "order" : "asc", // 排序方式
          "unit" : "km" // 排序的距离单位
      }
    }
  ]
}

3.3.2 分页

基本分页

elasticsearch 默认情况下只返回 top10的数据。而如果要查询更多数据就需要修改分页参数了。elasticsearch 中通过修改 from、size 参数来控制要返回的分页结果,类似于 mysql 中的 limit ?, ?

GET /hotel/_search  
{  
  "query": {  
    "match_all": {}  
  },  
  "from": 0, // 分页开始的位置,默认为0  
  "size": 10, // 期望获取的文档总数  
  "sort": [  
    {"price": "asc"}  
  ]  
}
深度分页

假设要查询990~1000的数据,在elasticsearch 内部分页时,必须先查询 0~1000条,然后截取其中的990 ~ 1000的这10条。

当查询分页深度较大时,汇总数据过多,对内存和 CPU 会产生非常大的压力,因此 elasticsearch 会禁止 from+ size 超过10000的请求。

针对深度分页,ES 提供了两种解决方案,官方文档

  • search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式。
  • scroll:原理将排序后的文档id形成快照,保存在内存。官方已经不推荐使用。
总结

分页查询的常见实现方案以及优缺点:

  • from + size
    优点:支持随机翻页
    缺点:深度分页问题,默认查询上限(from + size)是10000
    场景:百度、京东、谷歌、淘宝这样的随机翻页搜索
  • after search
    优点:没有查询上限(单次查询的 size 不超过10000)
    缺点:只能向后逐页查询,不支持随机翻页
    场景:没有随机翻页需求的搜索,例如手机向下滚动翻页
  • scroll
    优点:没有查询上限(单次查询的size不超过10000)
    缺点:会有额外内存消耗,并且搜索结果是非实时的
    场景:海量数据的获取和迁移。从 ES 7.1 开始不推荐,建议用 after search 方案。

3.3.3 高亮

高亮显示的实现分为两步:
1)给文档中的所有关键字都添加一个标签,例如<em>标签
2)页面给 <em> 标签编写 CSS 样式

GET /hotel/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT" // 查询条件,高亮一定要使用全文检索查询
    }
  },
  "highlight": {
    "fields": { // 指定要高亮的字段
      "FIELD": {
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签
        "post_tags": "</em>", // 用来标记高亮字段的后置标签
        "required_field_match": "false"//非搜索字段高亮时添加
      }
    }
  }
}

[!tip]
高亮是对关键字高亮,因此搜索条件必须带有关键字,而不能是范围这样的查询。

默认情况下,高亮的字段,必须与搜索指定的字段一致,否则无法高亮

如果要对非搜索字段高亮,则需要添加一个属性:
"required_field_match": "false"

3.4 Java 操作 DSL 查询

[!note]
黑马教程配套资料,有案例:黑马 ES DAY 02

第一步,创建 SearchRequest 对象,指定索引库名
第二步,利用 request.source() 构建 DSL,DSL 中可以包含查询、分页、排序、高亮等
第三步,利用 client.search()发送请求,得到响应

这里关键的 API 有两个,一个是 request.source(),其中包含了查询、排序、分页、高亮等所有功能:
image-20210721215640790
另一个是QueryBuilders,其中包含match、term、function_score、bool等各种查询:
image-20210721215729236

4 数据聚合

4.0 什么是数据聚合

聚合(aggregations) 可以让我们极其方便的实现对数据的统计、分析、运算。例如:

  • 什么品牌的手机最受欢迎?
  • 这些手机的平均价格、最高价格、最低价格?
  • 这些手机每月的销售情况如何?
    实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

4.1 聚合的种类

黑马 ES DAY 03

桶聚合(Bucket):用来对文档做分组
- TermAggregation:按照文档字段值分组,例如按照品牌值分组、按照国家分组
- Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组

度量聚合(Metric):用以计算一些值,比如:最大值、最小值、平均值等

  • Avg:求平均值
  • Max:求最大值
  • Min:求最小值
  • Stats:同时求max、min、avg、sum等

管道聚合(pipeline):其它聚合的结果为基础做聚合

[!tip]
注意:参加聚合的字段必须是 keyword、日期、数值、布尔类型

5 数据同步

常见的数据同步方案有三种:同步调用、异步通知、监听 binlog

5.1.1.同步调用

image-20210723214931869

基本步骤如下:

  • hotel-demo对外提供接口,用来修改elasticsearch中的数据
  • 酒店管理服务在完成数据库操作后,直接调用hotel-demo提供的接口,

5.1.2.异步通知

image-20210723215140735
流程如下:

  • hotel-admin对mysql数据库数据完成增、删、改后,发送MQ消息
  • hotel-demo监听MQ,接收到消息后完成elasticsearch数据修改

5.1.3.监听 binlog

image-20210723215518541

流程如下:

  • 给mysql开启binlog功能
  • mysql完成增、删、改操作都会记录在binlog中
  • hotel-demo基于canal监听binlog变化,实时更新elasticsearch中的内容

5.1.4.选择

方式一:同步调用

  • 优点:实现简单,粗暴
  • 缺点:业务耦合度高
    方式二:异步通知
  • 优点:低耦合,实现难度一般
  • 缺点:依赖mq的可靠性

方式三:监听binlog

  • 优点:完全解除服务间耦合
  • 缺点:开启 binlog 增加数据库负担、实现复杂度高

6 集群

单机的 elasticsearch 做数据存储,必然面临两个问题:海量数据存储问题、单点故障问题。

  • 海量数据存储问题:将索引库从逻辑上拆分为 N 个分片(shard),存储到多个节点
  • 单点故障问题:将分片数据在不同节点备份(replica )

ES 集群相关概念:

  • 集群(cluster):一组拥有共同的 cluster name 的节点。

  • 节点(node)集群中的一个 Elasticearch 实例

  • 分片:索引可以被拆分为不同的部分进行存储,称为分片。在集群环境下,一个索引的不同分片可以拆分到不同的节点中

    解决问题:数据量太大,单点存储量有限的问题。
    image-20200104124440086

    此处,我们把数据分成 3 片:shard 0、shard 1、shard 2

  • 主分片(Primary shard):相对于副本分片的定义。

  • 副本分片(Replica shard)每个主分片可以有一个或者多个副本,数据和主分片一样。

数据备份可以保证高可用,但是每个分片备份一份,所需要的节点数量就会翻一倍,成本实在是太高了!

为了在高可用和成本间寻求平衡,我们可以这样做:

  • 首先对数据分片,存储到不同节点
  • 然后对每个分片进行备份,放到对方节点,完成互相备份

这样可以大大减少所需要的服务节点数量,如图,我们以 3 分片,每个分片备份一份为例:

image-20200104124551912

现在,每个分片都有 1 个备份,存储在 3 个节点:

  • node 0:保存了分片 0 和 1
  • node 1:保存了分片 0 和 2
  • node 2:保存了分片 1 和 2

6.1. 搭建 ES 集群

参考 安装elasticsearch 部署 es 集群部分

6.2. 集群脑裂问题

6.2.1. 集群职责划分

elasticsearch 中集群节点有不同的职责划分:

image-20210723223008967

默认情况下,集群中的任何一个节点都同时具备上述四种角色。

但是真实的集群一定要将集群职责分离:

  • master 节点:对 CPU 要求高,但是内存要求第
  • data 节点:对 CPU 和内存要求都高
  • coordinating 节点:对网络带宽、CPU 要求高

职责分离可以让我们根据不同节点的需求分配不同的硬件去部署。而且避免业务之间的互相干扰。

一个典型的 es 集群职责划分如图:

image-20210723223629142

6.2.2. 脑裂问题

脑裂是因为集群中的节点失联导致的。

例如一个集群中,主节点与其它节点失联:

image-20210723223804995

此时,node 2 和 node 3 认为 node 1 宕机,就会重新选主:

image-20210723223845754

当 node 3 当选后,集群继续对外提供服务,node 2 和 node 3 自成集群,node 1 自成集群,两个集群数据不同步,出现数据差异。

当网络恢复后,因为集群中有两个 master 节点,集群状态的不一致,出现脑裂的情况:

image-20210723224000555

解决脑裂的方案是,要求选票超过 ( eligible 节点数量 + 1 )/ 2 才能当选为主,因此 eligible 节点数量最好是奇数。对应配置项是 discovery. zen. minimum_master_nodes,在 es 7.0 以后,已经成为默认配置,因此一般不会发生脑裂问题

例如:3 个节点形成的集群,选票必须超过 (3 + 1) / 2 ,也就是 2 票。node 3 得到 node 2 和 node 3 的选票,当选为主。node 1 只有自己 1 票,没有当选。集群中依然只有 1 个主节点,没有出现脑裂。

6.2.3. 小结

master eligible 节点的作用是什么?

  • 参与集群选主
  • 主节点可以管理集群状态、管理分片信息、处理创建和删除索引库的请求

data 节点的作用是什么?

  • 数据的 CRUD

coordinator 节点的作用是什么?

  • 路由请求到其它节点

  • 合并查询到的结果,返回给用户

标签:笔记,查询,索引,文档,分片,Elasticsearch,节点,集群
From: https://www.cnblogs.com/licwuu/p/18341267

相关文章

  • 扫描线学习笔记
    前言扫描线思想可以在\(O(n^2)\)的时间复杂度内进行二维平面的计算,运用线段树优化可以在\(O(n\logn)\)的时间复杂度内解决。简介P5490【模板】扫描线以此题为例,介绍扫描线。最直接的想法是将每个正方形的面积先加起来,最后再减去重叠部分,但是代码难度较大,不易于实现。......
  • 矩阵学习笔记
    矩阵引入矩阵引入来源于简洁表示线性方程组例如:\[\begin{cases}2x+5y=10\\4x+9y=39\end{cases}\]可以表示为:\[\begin{bmatrix}2&5\\4&9\end{bmatrix}\times\begin{bmatrix}x\\y\end{bmatrix}\]矩阵乘法定义矩阵\(A\)为\(n\timesm\)的矩阵,\(B\)为\(......
  • 树的基础学习笔记
    树的直径定义:树上最长的简单路径。(可能有多条)树的直径的性质直径两端点一定是两个叶子节点。距离任意点最远的点一定是直径的一个端点,这个基于贪心求直径方法的正确性可以得出。对于两棵树,如果第一棵树直径两端点为(u,v),第二棵树直径两端点为\((x,y)\),用条边将两棵树......
  • OpenStack Yoga版安装笔记(十二)nova安装(下)
    5、InstallandconfigurecontrollernodeforUbuntu注意安装版本为:nova25.2.2.dev55.1Prerequisites在安装和配置compute service之前,需要先创建数据库、服务凭证(用户名/密码)、服务API端点。1、Createthedatabase:root@controller:~#mysqlWelcometotheMariaDB......
  • Python学习笔记51:暂停篇
    随便写点最近因为公司项目的原因,学习进度变慢很多,但是也勉强支撑着把小游戏的项目写了个大概,其实后续很多的功能基本都是慢慢添加就可以,掌握了函数的调用,磕磕碰碰终究还是能把功能写好的,可能就是代码质量差一点,但是这个没必要过于纠结,写的多了看的多了,慢慢的就会进步。一......
  • Datawhale AI夏令营(笔记③)
    #DatawhaleAI夏令营##AI##夏令营#    今天的主要内容是学习如何用Transformer建模SMILES进行反应产率预测。Task2(即笔记②)中,我们学习使用RNN建模SMILES,且发现了RNN在处理这类问题的局限性。那么今天,我们就跟着本节内容,看看Transformer是如何解决RNN的缺陷的。一......
  • Noip 真题笔记
    Noip2023A事实上只需要比较最大一个和最小一个就可以了。注意排序后的字符串是递增或递减的,是用递增字符串与其他的递减字符串比较。B考场不会。综述:对DFS的详细描述:Noip2022悲惨的一年,对这一年真题有问题别问学长。A签到。当时我写了个三方还艹过去了。对于三......
  • 矩阵树定理学习笔记
    用来求和一个图的生成树个数相关的算法,时间复杂度\(O(n^3)\)。你要会求一个矩阵的行列式,这是和行列式有关的前置知识。定理阐述对于无向图定义度数矩阵\(D_{i,j}=[i=j]\deg_i\),其中\(\deg_i\)表示\(i\)的度数。定义邻接矩阵为\(E_{i,j}\)为边\((i,j)\)的个数。定......
  • 笔记——AVL树
    和普通的二叉搜索树的区别:普通的二叉搜索树只满足左子树小于个根,右子树大于根,不会进行平衡(降低高度)这就导致可能退化,这样查找插入数据的时间复杂度就是o(n)而为了防止二叉搜索树退化,AVL树引入了平衡因子的概念,使树的每一层都是满的,只有树的一层满后才插入下一层,利用平衡因......
  • OpenCV计算机视觉学习(16)——仿射变换学习笔记
    如果需要其他图像处理的文章及代码,请移步小编的GitHub地址传送门:请点击我如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice在计算机视觉和图像处理中,仿射变换是一种重要的几何变换方法。它可以通过线性变换和平移来改变图像的形状和位置,广泛应......