Elasticsearch基础总结

  Elasticsearch是一款开源、近实时、高性能的分布式搜索引擎。

  Elasticsearch底层基于Lucene开发,针对Lucene的局限性,ES提供了RESTful API风格的接口、支持分布式、可水平扩展。

 

 

 前言—生活中的数据

  搜索引擎是对数据的检索,所以我们要从生活中的数据说起,总体分为两种:

    结构化数据

    非结构化数据

  结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。指具有固定格式或有限长度的数据,如数据库,元数据等

  非结构化数据:也可称为全文数据,不定长或无固定格式,不适于由数据库二维表来表现,包括所有格式的文档,如xml、html、word、邮件、各类图表、图片和音频、视频信息等

  对于结构化数据,因为它们具有特定的结构,所以我们一般都是通过关系型数据库(MySQL等)的二维表的方式存储和搜索,也可建立索引

  对于非结构化数据,也即对全文数据的搜索主要有两种方法:

    ①:顺序扫描

      按照顺序扫描的方式查询特定的关键字

    ②:全文检索

      将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的

      这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之为索引

 

  ES7版本的变化:

    TransportClient被废弃

    废除单个索引下多Type的支持,使用默认的_doc 作为Type,同时在8.x版本将彻底废除type

 

 一、基本概念

  index,索引,在ES中,索引有两个含义:

    1)名词:一个索引相当于关系型数据库中的一张表

    2)动词:将一份document保存在一个index中,这个过程称为索引

  type

    在6.x之前,index可以被理解为关系型数据库中的【数据库】,而type则可以被认为是【数据库中的表】。

    使用type允许我们在一个index里存储多种类型的数据,数据筛选时可以指定type。type的存在从某种程度上可以减少index的数量,但是type存在以下限制:

      ①:不同type里的字段需要保持一致。例如,一个 index 下的不同 type 里有两个名字相同的字段,他们的类型(string, date 等等)和配置也必须相同

      ②:只在某个 type 里存在的字段,在其他没有该字段的 type 中也会消耗资源

      ③:得分是由 index 内的统计数据来决定的。也就是说,一个 type 中的文档会影响另一个 type 中的文档的得分

    以上限制要求我们,只有同一个 index 的中的 type 都有类似的映射 (mapping) 时,才勉强适用 type 。否则,使用多个 type 可能比使用多个 index 消耗的资源更多。
    这大概也是为什么 ES 决定废弃 type 这个概念,个人感觉 type 的存在,就像是一个语法糖,但是并未带来太大的收益,反而增加了复杂度

    

  document,文档

    index中的单条记录称为document,可以理解为表中的一行数据,多条document组成了一个index

  field,字段

    一个document会由一个或多个field组成,field是ES中数据索引的最小单位

    在ES中,没有数组类型,任何字段都可以变成数组

    ES中常用的类型:

string text 1、索引全文值的字段,如电子邮件正文或产品描述
2、出于不同目的,我们期望以不同方式索引同一字段,这就是milti-fileds(多字段)。
    如可以将string字段映射为用于全文搜索的text字段
    并映射为用于排序或聚合的keyword字段
注意:
  纯text字段默认无法进行排序或聚合
  使用text字段一定要使用合理的分词器
keyword

存储的是原始内容

用于索引结构化内容的字段,例如ID、电子邮件地址,主机名、状态代码、邮政编码或标签

通常用于过滤、排序或聚合,keyword字段只能精准匹配

numeric  整数类型

byte、short、integer、long

我们应该选择足以满足用例的最小类型

浮点类型

使用缩放因子(scaled_float)将浮点数据存储到整数中通常更有效

如果scaled_float无法满足精度要求,可以使用double、float、half_float

⚠️ 不是所有的字段都适合存储为numberic,numberic类型更擅长range类查询,精确查询可以尝试使用keyword  

                     

   mapping,映射

    mapping是一个定义document结构的过程,mapping中定义了一个文档所包含的所有field信息

    定义字段索引过多会导致爆炸的映射,这可能会导致内存不足错误和难以恢复的情况, mapping 提供了一些配置对 field 进行限制,下面列举几个可能会比较常见的:
      index.mapping.total_fields.limit 限制 field 的最大数量,默认值是 1000(field 和 object 内的所有字段,都会加入计数)。
      index.mapping.depth.limit 限制 object 的最大深度,默认值是 20。
      index.mapping.field_name_length.limit 限制中字段名的长度,默认是没有限制

    dynamic mapping

      动态映射,在索引document时,ES的动态映射会将新增内容中不存在的字段,自动的加入到映射关系中。ES会自动检测新增字段的逻辑,并赋予其默认值

    ⚠️ 在ES中,删除/变更 field定义,需要进行reindex,所以在构建mapping结构时记得评估好字段的用途,以使用最合适的字段类型。

 

  

  检索 

    match:用于执行全文查询的标准查询,包括模糊匹配和短语或接近查询。

      重要参数,控制token之间的布尔关系:or/and

    match_phrase:与match查询类似,但用于匹配确切的短语或单词接近匹配。

      重要参数,token之间的位置距离,slop,默认为0

    term:精确查找的关键,在lucene中,term是索引和搜索的最小单位。一个field会由一个或多个term组成,term是由field经过analyzer(分词)产生。

      term dictionary即term词典,是根据条件查找term的基本索引

      ⚠️ 注意:

        避免对text字段使用term查询。默认情况下,ES会在分析过程中更改文本字段的值,这会使查找text字段值的精确匹配变得困难。要搜索text字段值,强烈建议使用match查询

        默认分词情况下,无论是term还是match,都无法判断text类型字段是否为空字符串

      因为,text字段存储的是分词结果,如果字段值为空,分词结果将不会存储 term 信息,keyword字段存储的是原始内容。      

      

  similarity 相似性得分

   1、TF/IDF(v7版本已禁止使用,v8彻底废除)

    TF-IDF=词频(TF)*  逆文档频率(IDF)

    TF/IDF 使用逆文档频率作为权重,降低常见词汇带来的相似性得分。从公式中可以看出,这个相似性算法仅与文档词频相关,覆盖不够全面。

    例如:缺少文档长度带来的权重,当其他条件相同,“王者荣耀”这个查询关键字同时出现在短篇文档和长篇文档中时,短篇文档的相似性其实更高

     在 ESV5 之前,ES 使用的是 Lucene 基于 TF/IDF 自实现的一套相关性得分算法,如下所示:

    score(q,d)  =
            queryNorm(q)
          · coord(q,d)
          · ∑ (
                tf(t in d)
              · idf(t)²
              · t.getBoost()
              · norm(t,d)
            ) (t in q)
queryNorm query normalization factor 查询标准化因子,旨在让不同查询之间的相关性结果可以进行比较(实际上 ES 的 tips 中提到,并不推荐大家这样做,不同查询之间的决定性因素是不一样的)
coord coordination factor 协调因子,query 经过分析得到的 terms 在文章中命中的数量越多,coord 值越高。例如:查询“王者荣耀五周年”,terms:“王者”、“荣耀”、“五周年”,同时包含这几个 term 的文档 coord 值越高
tf 词频
idf   文档逆频率
boost boost字面意思是增长推动,这里可以理解为一个支持可配的加权参数
norm 文档长度标准化,内容越长,值越小

   Lucene 已经针对 TF/IDF 做了尽可能的优化,但是有一个问题仍然无法避免词频饱和度问题,TF/IDF 算法的相似性得分会随着词频不断上升。在 Lucene 现有的算法中,如果一个词出现的频率过高,会直接忽略掉文档长度带来的权重影响

 

   2)BM25,默认    

    BM25相比TF-IDF的优点

    ①:词频饱和不同于 TF/IDF,BM25 的实现基于一个重要发现:“词频和相关性之间的关系是非线性的”。当词频到达一定阈值后,对相关性得分的影响是相同的,此时应该由其他因素的权重决定得分高低,例如之前提到的文档长度

    ②:将文档长度加入算法中,相同条件下,短篇文档的权重值会高于长篇文档

    ③:提供了可调整的参数

 

 

  除了进行全文搜索,Elasticsearch也支持聚合/排序

  sort排序

    在执行ES查询时,默认的排序规则是根据相关性得分倒序排序,针对非全文索引字段,可以指定排序方式,使用也很简单,如:

//查询时先根据tab_id降序排列,若tab_id相同,则根究status升序排列
GET /[your index]/_search
{
  "sort": [
    {"tab_id": {"order": "desc"}},
    {"status": {"order": "asc"}}
  ]
}

    注意,针对缺失数值类字段的默认值并不是 0,ES 默认会保证排序字段没有 value 的文档被放在最后,默认情况下:

      ①:降序排列,缺失字段默认值为该字段类型的最小值

      ②:升序排列,缺失字段默认值为该字段类型的最大值

    ES为我们提供了missing参数,我们可以指定缺失值填充,其默认值为_last。

// with missing
GET /[your index]/_search
{
  "sort": [
    {
      "num": {
        "order": "asc",
        "missing": "0"
      }
    }
  ]
}

   使用function score 实现自定义排序

    当我们期望查询结果按照某个类型进行排序,或者查询结果顺序由多个字段的权重组合决定的场景时,可以使用function score自定义排序,部分参数介绍:

weight 权重值
boost 加权值
boost_mode 加权值计算方式,默认为multiple
score_mode 得分计算方式,默认为multiple

 

    视频类型查询,电视剧tv的优先级高于电影movie的优先级:

GET /my_index/_search
{
  "explain": true,
  "query": {
    "function_score": {
      "functions": [
        {
          "filter": {"term": {"type": "movie"}},
          "weight": 1
        },
        {
          "filter": {"term": {"type": "tv"}},
          "weight": 2
        }
      ],
      "boost": 1,
      "score_mode": "sum"
    }
  }
}

 

 聚合aggs

    聚合操作可以帮助我们将查询数据按照指定的方式进行归类。常见的聚合方式,诸如:

    max、min、avg、range、根据term聚合等

 

  索引别名

    Aliases 索引别名 索引别名,顾名思义,定义了别名之后,可以通过别名对 index 进行查询:PUT /[your index]/_alias/[your alias name]

  索引生命周期策略

    Index Lifecycle Policies 索引生命周期策略 索引生命周期策略支持我们根据天、存储量级等信息去自动管理我们的索引。创建方式可以通过 RESTful API,也可以直接在 kibana 上创建,可视化界面看起来比较清晰~ 支持配置满足一定规则后索引自动变化:

      自动滚动索引(hot)

      保留索引仅供检索(warm)

      保留索引仅供检索同时减少磁盘存储(cold)

      删除索引

  索引模版

    Template 索引模板 通过 index_patterns 参数设置索引名正则匹配规则,向一个不存在的索引 POST 数据,命中索引名规则后即会根据索引模版创建索引,不会进行动态映射    

    

  索引模式

    

 

END.

posted @ 2022-05-01 00:42  杨岂  阅读(119)  评论(0编辑  收藏  举报