Elasticsearch 技术分享
文章目录
一,Elasticsearch 基础介绍
1.简介
Elasticsearch是一个高度可扩展的、开源的、基于 Lucene 的全文搜索和分析引擎。它允许您快速,近实时地存储,搜索和分析大量数据
Elasticsearch其实它是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。
而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。
2.kibana
Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。可以用Kibana搜索,查看和与存储在 Elasticsearch 索引中的数据进行交互。您可以轻松地执行高级数据分析,并在各种图表,表格和地图中可视化您的数据。
注意:在开发中jar的版本和ELK(ElasticSearch, logstash, kibana)技术栈的版本统一
3.基本概念
-
索引(Index)
索引是具有某些类似特征的文档集合。例如,您可以拥有店铺数据的索引,商品的一个索引以及订单数据的一个索引。 -
类型(Type)6.0.0版本中弃用
类型,曾经是索引的逻辑类别/分区,允许您在同一索引中存储不同类型的文档,例如,一种类型用于用户,另一种类型用于博客帖子。 -
文档(Document)
文档是可以建立索引的基本信息单元。例如,您可以为单个客户提供文档,为单个产品提供一个文档,为单个订单提供一个文档。该文档以JSON表示 -
分片(Shards)
索引可能存储大量可能超过单个节点的硬件限制的数据。例如,占用1TB磁盘空间的十亿个文档的单个索引可能不适合单个节点的磁盘,或者可能太慢而无法单独从单个节点提供搜索请求。它允许您跨分片(可能在多个节点上)分布和并行化操作,从而提高性能/吞吐量 -
副本(Replicasedit)
副本,是对分片的复制。目的是为了当分片/节点发生故障时提供高可用性,它允许您扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索。
注意:副本是乘法,越多越浪费,但也越保险。分片是除法,分片越多,单分片数据就越少也越分散。
关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。
Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。
4.索引的应用
- 创建索引
PUT project_v1
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name_cn": {
"type": "text"
},
"name_en": {
"type": "keyword"
},
"project_type": {
"type": "keyword"
},
"people_count": {
"type": "integer"
},
"order_count": {
"type": "long"
},
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||yyyy-MM||epoch_millis"
}
}
}
}
text 用于索引全文值的字段,例如电子邮件正文或产品说明。它们通过分词器传递 ,以在被索引之前将字符串转换为单个术语的列表。分析过程允许Elasticsearch搜索单个单词中 每个完整的文本字段。文本字段不用于排序,很少用于聚合。
keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们通常用于过滤,排序,和聚合。keyword字段只能按其确切值进行搜索。
有时候一个字段同时拥有全文类型(text)和关键字类型(keyword)是有用的:一个用于全文搜索,另一个用于聚合和排序。
- 新增索引数据
PUT /project_v1/_doc/1
{
"name_en":"encourage",
"name_cn":"营销码",
"project_type":"营销",
"people_count":4,
"order_count":1000000,
"date":"2019-04-01"
}
PUT /project_v1/_doc/2
{
"name_en":"encourageBoard",
"name_cn":"营销看板",
"project_type":"营销",
"people_count":2,
"order_count":1000000,
"date":"2020-04-15"
}
PUT /project_v1/_doc/3
{
"name_en":"seperate",
"name_cn":"分账中心",
"project_type":"结算",
"people_count":3,
"order_count":10000,
"date":"2020-07-30"
}
PUT /project_v1/_doc/4
{
"name_en":"sale",
"name_cn":"代办点",
"project_type":"营销",
"people_count":4,
"order_count":500000,
"date":"2020-11-04"
}
- 查询索引数据
GET /project_v1/_search
{
"query": {
"match_all": {}
}
}
- 匹配查询 match
GET /project_v1/_search
{
"query": {
"match": {
"name_cn": "营销"
}
}
}
- 过滤查询 Filter
GET /project_v1/_search
{
"query": {
"bool": {
"filter": {
"range": {
"date": {
"gte": "2020-04-01"
}
}
}
}
}
}
二,Elasticsearch 聚合查询
1.聚合的概念
官方对聚合有四个关键字:Metric(指标)、Bucketing(桶)、Pipeline(管道)、Matrix(矩阵),在查询请求体中以aggregations语法来定义聚合分析,也可简写成aggs
Metric(指标):指标分析类型,如计算最大值、最小值、平均值等(对桶内的文档进行聚合分析的操作)
Bucket(桶):分桶类型,类似sql中的group by语法(满足特定条件的文档的集合)
Pipeline(管道):管道分析类型,基于上一级的聚合分析结果进行再分析
Matrix(矩阵):矩阵分析类型(聚合是一种面向数值型的聚合,用于计算一组文档字段中的统计信息)
2.Metric(指标)聚合
Metric聚合分析分为单值分析和多值分析两类
1、单值分析,只输出一个分析结果
关键字有min, max,avg,sum,cardinality
2、多值分析,输出多个分析结果
关键字有stats,extended_stats,percentile_rank,top hits
- min, max,avg, sum
GET /project_v1/_search
{
"size": 0,
"aggs": {
"min_people_count": {
"min": {
"field": "people_count"
}
},
"max_order_count":{
"max": {
"field": "order_count"
}
},
"avg_order_count":{
"avg": {
"field": "order_count"
}
},
"sum_order_count":{
"sum": {
"field": "order_count"
}
}
}
}
- cardinality
GET /project_v1/_search
{
"size": 0,
"aggs": {
"cardinality_project_type": {
"cardinality": {
"field": "project_type"
}
}
}
}
- stats
GET /project_v1/_search
{
"size": 0,
"aggs": {
"stats_order_count": {
"stats": {
"field": "order_count"
}
}
}
}
- extended_stats
GET /project_v1/_search
{
"size": 0,
"aggs": {
"extended_stats_order_count": {
"extended_stats": {
"field": "order_count"
}
}
}
}
3.Bucket(桶)聚合
Bucket可以理解为一个桶,它会遍历文档中的内容,凡是符合某一要求的就放在一个桶中,分桶相当于sql中的group by
关键字有Terms Aggregation,Filter Aggregation,Histogram Aggregation,Date Aggregation
- Terms Aggregation
根据某一项的每个唯一的值来聚合
GET /project_v1/_search
{
"size": 0,
"aggs": {
"terms_project_type": {
"terms": {
"field": "project_type",
"size": 3
}
}
}
}
- Filter Aggregation
指具体的域和具体的值,可以在Terms Aggregation 的基础上进行了过滤,只对特定的值进行了聚合
#查营销类型的总订单数
GET /project_v1/_search
{
"size": 0,
"aggs": {
"filter_project_type": {
"filter": {
"term": {
"project_type": "营销"
}
},
"aggs": {
"sum_order_count": {
"sum": {
"field": "order_count"
}
}
}
}
}
}
- Histogram Aggregation
Histogram与Terms聚合类似,都是数据分组,区别是Terms是按照Field的值分组,而Histogram可以按照指定的间隔对Field进行分组
#项目规模
GET /project_v1/_search
{
"size": 0,
"aggs": {
"project_scale": {
"histogram": {
"field": "people_count",
"interval": 1
}
}
}
}
- Date Aggregation
针对时间格式数据的直方图聚合,基本特性与Histogram Aggregation一致
#项目发展史
GET /project_v1/_search
{
"size": 0,
"aggs": {
"date_by_day": {
"date_histogram": {
"field": "date",
"calendar_interval": "day",
"min_doc_count": 1
}
}
}
}
4.Pipeline(管道)聚合
管道的概念:支持对聚合分析的结果,再次进行聚合分析
#查项目类型最少人数的项目类型
GET /project_v1/_search
{
"size":0,
"aggs":{
"project_type":{
"terms": {
"field": "project_type",
"size": 3
},
"aggs":{
"sum_people_count":{
"sum": {
"field": "people_count"
}
}
}
},
"min_people_count_by_project_type":{
"min_bucket": {
"buckets_path": "project_type>sum_people_count"
}
}
}
}
5.Matrix(矩阵)聚合
略
6.总结
Metric(指标):分类并对一组文档进行sum、avg等数学运算
Bucketing(桶):桶聚合,常规的分类然后计算每个分类的文档数量
Pipeline(管道):对聚合的结果再次聚合
Matrix(矩阵):可在多个字段上计算,生成矩阵结果
三,Elasticsearch 索引别名Aliases
1.业务问题
业务需求是不断变化迭代的,也许我们之前写的某个业务逻辑在下个版本就变化了,我们可能需要修改原来的设计,例如数据库可能需要添加一个字段或删减一个字段,而在搜索中也会发生这件事,即使你认为现在的索引设计已经很完美了,在生产环境中,还是有可能需要做一些修改的,需要添加映射字段或者需要修改字段类型等等。
数据库中我们可以直接修改原来的表设计语句,前提是需要做好数据迁移。但是在 Elasticsearch 中就没那么简单了。尽管可以增加新的类型到索引中,或者增加新的字段到类型中,但是不能添加新的分析器或者对现有的字段做改动。如果你那么做的话,结果就是那些已经被索引的数据就不正确,搜索也不能正常工作。针对这个问题必须重新建立索引。
2.别名定义
假设我们有个学生的原始索引 project_v1,我们给它起个别名 project_index,程序中也是用别名 project_index 进行搜索,当我们的业务需求发生改变需要修改索引的时候,我们重新创建个索引 project_v2,同时将别名 project_index 指向新的索引 project_v2,同时将 project_v1 的数据迁移到新的project_v2,这样我们就可以做到在零停机下从旧索引切换到新索引。
索引别名就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何一个需要索引名的API来使用,而且别名不能与索引同名。
别名带给我们极大的灵活性,允许我们做下面这些:
3.别名管理
别名还可以映射到某个索引也可以映射到多个索引。别名还可以与筛选器关联,筛选器将在搜索和路由值时自动应用,别名不能与索引同名。
Elasticsearch 中有两种方式管理别名: _alias 用于单个操作, _aliases 用于执行多个原子级操作。
- 单个索引别名
POST /_aliases
{
"actions": [
{
"add": {
"index": "project_v1",
"alias": "project_index"
}
}
]
}
- 删除别名
POST /_aliases
{
"actions": [
{
"remove": {
"index": "project_v1",
"alias": "project_index"
}
}
]
}
- 别名与多个索引关联
POST /_aliases
{
"actions": [
{
"add": {
"index": "project_v1",
"alias": "project_index"
}
},
{
"add": {
"index": "project_v2",
"alias": "project_index"
}
}
]
}
4.Filtered Aliases
过滤器别名提供了一个简单的方法对同一个索引来创建不同的“视图”。过滤器能够使用Query DSL来定义并且被应用到所有的搜索,统计,通过查询删除和其它类似的行为。
POST /_aliases
{
"actions": [
{
"add": {
"index": "project_v1",
"alias": "project_sale",
"filter": {
"term": {
"name_en": "sale"
}
}
}
}
]
}
这样设置之后,我们通过索引 project_v1 直接进行搜索可以看到索引的全部文档,但是通过别名 project_sale 这个别名就只能看到符合过滤器过滤后的结果了,即只有一个 name_en 为 “sale” 的结果。
5.Write Index Aliases
通过设置Write Index Aliases ,这样就可以用别名新增索引数据
POST /_aliases
{
"actions": [
{
"add": {
"index": "project_v2",
"alias": "project_index",
"is_write_index": true
}
},
{
"add": {
"index": "project_v1",
"alias": "project_index"
}
}
]
}
PUT /project_index/project/2
{
"name_en":"express",
"name_cn":"车管",
"date":"2019-09-19"
}
6.别名关系
检测别名指向哪一个索引:
GET /*/_alias/project_index
或这个索引指向哪个别名:
GET /project_v1/_alias/*
四,通过SQL查询Elasticsearch
1.为什么用SQL查询
Elasticsearch 的官方查询语言是 Query DSL,既然是官方指定的,说明最吻合 ES 的强大功能,为ES做支撑。那么我们为什么还用 sql 查询?这是否是多此一举了呢?
其实,sql 作为一个数据库查询语言,它语法简洁,书写方便而且大部分服务端程序员都清楚了解和熟知它的写法。但是作为一个 ES 萌新来说,就算他已经是一位编程界的老江湖,但是如果他不熟悉 ES ,那么他如果要使用公司已经搭好的 ES 服务,他必须要先学习 Query DSL,学习成本也是一项影响技术开发进度的因素而且不稳定性高。但是如果 ES 查询支持 sql的话,那么也许就算他是工作一两年的同学,他虽然不懂 ES的复杂概念,他也能很好的使用 ES 而且顺利的参加到开发的队伍中,毕竟sql 谁不会写呢?
2.Elasticsearch-sql
Elasticsearch-sql不属于 Elasticsearch 官方的,它是 NLPChina(中国自然语言处理开源组织)开源的一个 ES 插件,主要功能是通过 sql 来查询 ES,其实它的底层是通过解释 sql,将sql 转换为 DSL 语法,再通过DSL 查询。
查询语法
SELECT fields from indexName/type WHERE conditions
表名 tableName 的地方现在改为了索引名 indexName,如果有索引Type ,则indexName/type
POST _sql?format=txt
{
"query": "select * from project_index limit 10"
}
sql翻译成DSL语句
POST _sql/translate
{
"query": "select name_en,COUNT(*) from project_index GROUP BY name_en"
}
五,常见问题
1.版本问题
es 5到7的版本变动很大,其中包括type的变动
2.ES并不可靠
ES不是可靠的存储系统,不是数据库,它有丢数据的风险。ES不是实时系统,数据写入成功只是trans log成功(类似于MysqL的bin log),写入成功后立刻查询查不到是正常的。因为数据此刻可能还在内存里而不是进入存储引擎里。
3.同步问题
在需要添加新数据与新字段的时候,如果elasticSearch进行搜索是可能需要重新修改格式。之前的数据需要重新同步,对数据的管理有很多困难。
LogStash同步数据至ES
https://blog.csdn.net/crazyo2jam/article/details/104938817
基于JPA同步数据至ES
https://blog.csdn.net/KingBoyWorld/article/details/78654820
4.性能问题
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。