• 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.

  • 相关阅读:
    动态规划算法
    MapReduce学习笔记(4)
    MapReduce学习笔记(3)
    MapReduce学习笔记(2)
    Intellij IDEA output 中文乱码
    Spring实例化bean的三种方式
    Spring框架捕获所有URL的请求的处理方案
    异常解决:Mapped Statements collection does not contain value for …
    Java包 package 的命名规范, 命名规则
    拦截器 Filter : js、css、jpg、png等静态资源不被拦截解决方案
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/16211999.html
Copyright © 2020-2023  润新知