微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Elasticsearch 技术分享

Elasticsearch 技术分享

文章目录

一,Elasticsearch 基础介绍

1.简介

Elasticsearch是一个高度可扩展的、开源的、基于 Lucene 的全文搜索和分析引擎。它允许您快速,近实时地存储,搜索和分析大量数据

Elasticsearch其实它是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。

除了Lucene 和全文搜索,还有以下功能

  • 分布式的实时文件存储,每个字段都被索引并可被搜索
  • 分布式的实时分析搜索引擎
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。

2.kibana

Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。可以用Kibana搜索,查看和与存储在 Elasticsearch 索引中的数据进行交互。您可以轻松地执行高级数据分析,并在各种图表,表格和地图中可视化您的数据。

注意:在开发中jar的版本和ELK(ElasticSearch, logstash, kibana)技术栈的版本统一

3.基本概念

  1. 索引(Index)
    索引是具有某些类似特征的文档集合。例如,您可以拥有店铺数据的索引,商品的一个索引以及订单数据的一个索引。

  2. 类型(Type)6.0.0版本中弃用
    类型,曾经是索引的逻辑类别/分区,允许您在同一索引中存储不同类型的文档,例如,一种类型用于用户,另一种类型用于博客帖子。

  3. 文档(Document)
    文档是可以建立索引的基本信息单元。例如,您可以为单个客户提供文档,为单个产品提供一个文档,为单个订单提供一个文档。该文档以JSON表示

  4. 分片(Shards)
    索引可能存储大量可能超过单个节点的硬件限制的数据。例如,占用1TB磁盘空间的十亿个文档的单个索引可能不适合单个节点的磁盘,或者可能太慢而无法单独从单个节点提供搜索请求。它允许您跨分片(可能在多个节点上)分布和并行化操作,从而提高性能/吞吐量

  5. 副本(Replicasedit)
    副本,是对分片的复制。目的是为了当分片/节点发生故障时提供高可用性,它允许您扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索

注意:副本是乘法,越多越浪费,但也越保险。分片是除法,分片越多,单分片数据就越少也越分散。

可以画一个对比图来类比传统关系型数据库

关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。
Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。

4.索引的应用

  1. 创建索引
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)是有用的:一个用于全文搜索,另一个用于聚合和排序。

  1. 新增索引数据
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"
}
  1. 查询索引数据
GET /project_v1/_search
{
  "query": {
    "match_all": {}
  }
}
  1. 匹配查询 match
GET /project_v1/_search
{
  "query": {
    "match": {
      "name_cn": "营销"
    }
  }
}
  1. 过滤查询 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

  1. 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"
      }
    }
  }
}
  1. cardinality

cardinality 关键字: 求唯一值,即不重复的字段有多少(相当于sql中的distinct)

GET /project_v1/_search
{
  "size": 0,
  "aggs": {
    "cardinality_project_type": {
      "cardinality": {
        "field": "project_type"
      }
    }
  }
}
  1. stats

统计信息,请求后会直接显示各种聚合结果(count,min,max,avg,sum)

GET /project_v1/_search
{
  "size": 0,
  "aggs": {
    "stats_order_count": {
      "stats": {
        "field": "order_count"
      }
    }
  }
}
  1. extended_stats

扩展的统计信息,比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

  1. Terms Aggregation

根据某一项的每个唯一的值来聚合

GET /project_v1/_search
{
  "size": 0,
  "aggs": {
    "terms_project_type": {
      "terms": {
        "field": "project_type",
        "size": 3
      }
    }
  }
}
  1. 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"
          }
        }
      }
    }
  }
}
  1. Histogram Aggregation

Histogram与Terms聚合类似,都是数据分组,区别是Terms是按照Field的值分组,而Histogram可以按照指定的间隔对Field进行分组

#项目规模
GET /project_v1/_search
{
  "size": 0,
  "aggs": {
    "project_scale": {
      "histogram": {
        "field": "people_count",
        "interval": 1
      }
    }
  }
}
  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 用于执行多个原子级操作。

  1. 单个索引别名
POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "project_v1",
        "alias": "project_index"
      }
    }
  ]
}
  1. 删除别名
POST /_aliases
{
  "actions": [
    {
      "remove": {
        "index": "project_v1",
        "alias": "project_index"
      }
    }
  ]
}
  1. 别名与多个索引关联
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的变动

  • 5.x 支持多种type

  • 6.x 只能有一种type

  • 7.x 将去除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] 举报,一经查实,本站将立刻删除。

相关推荐