ElasticSearch

1. 基础篇

本文档主要基于 https://www.cnblogs.com/progor/p/11543146.html 这篇博客.

1.1 介绍

1.2 基本概念

  • 索引 Index: 索引是存储具有相同结构的 Document 的集合, 意义上有点类似关系型数据库中的数据表, 用于存储一系列数据, 比如可以说 “商品” 索引, 一般都是个大类. 注意, 通常我们要避免将 Schema 差异过大的 Document 放在一个 Index 中. 这和底层 Mapping 机制有关. 再 7.0 之前有一个隐藏字段 _type 通常用来做逻辑上的 Table 的划分, 但后来官方发现同一个 Index 下的 Schema 差异太大导致维护的字段过多, 所以从 7.0 开始就限制一个 Index 下只有一个 Type, 也就是说 Type 的概念没有用了. (2021-11-27 目前是 7.5版本)

  • 文档 Document: 类似于关系型数据库中的记录, 是 ElasticSearch 的数据存储的基本单位, 格式与 JSON 相同.

  • 域 Field: 类似于关系型数据库中的字段。

1.2.1 索引 Index

Links:

创建索引

你在插入 Document 时, 如果 Index 还没有被创建, 那么 ES 会自动用默认设置创建这个 Index. 当然你也可以手动创建 Index 并对其进行更精细的配置.

修改索引

修改索引主要是修改分片数量, mapping, 分词器, 由于 mapping 和 分词器 涉及很深, 需要前置知识, 所以留到后面讲.

关闭索引

关闭索引是为了避免修改索引的配置时他人进行文档读写. 关闭索引后, 就只能获取索引的配置信息, 而不能读写索引中的 Document. 有时候也用于关闭一些无用的索引来减少资源消耗.

索引别名

索引别名是一个 “别名”, 但能够像索引名那样使用, 它的使用场景一方面是 “使用更简洁的索引名来获取数据”, 另一个方面是 “通过索引别名来指向索引 (别名B指向索引A), 方便修改指向的索引, 用于解决可能的更换索引的场景 (比如你需要统一修改原有索引的信息, 那你可以新建索引C, C存储了修改后的数据, 更改指向原本索引A的索引别名B指向C).”

1.2.2 文档 Document

在 ElasticSearch 中, Document 是 Immutable 并且有 Versioned. 默认情况下你搜索到的都是最新的数据. 比如你插入后对文档某字段进行了修改, 版本号就会 +1. 你在查询的时候返回的结果会带有 _version 字段, 表示该文档的版本号.

1.3 查询

Links:

1.3.1 基础查询

ES 的查询功能是非常强大且灵活的. 其中作为杀手锏的是搜索引擎中常用的倒排索引. 简单来说, 查询的请求 JSON 长这个样子:

{
  "query": {
    ... 具体的查询
  }
}

ES 的查询模式有这几大类:

  1. Leaf query clauses. 主要是三个: match 全文搜索查询, term 精确值匹配查询, range 数值区间查询.

  2. Compound query clauses. 其实就是 Leafe query clauses 的逻辑与或非排列组合. 主要是两个: bool 逻辑组合, dis_max 文本距离查询. 以及一个特殊的 constant_score 指定某些查询条件不参与相关度排序.

  3. 慢查询, 这些查询通常无法有效利用索引
    • script 在 Query DSL 中写简单的 script, 对数据进行简单处理和匹配.

    • fuzzy

    • regexp

    • prefix

    • wildcard

    • range on text and keyword

    • Joining 跨 Index Join 查询.

  • match_all, 全部字段的全文搜索:

{
  "query": {
    "match_all": {}
  }
}
  • match, 指定字段的全文搜索:

{
  "query": {
    "match": {
      "字段名": "搜索值"
    }
  }
}
  • multi_match, 使用同一搜索值值搜索多个字段:

{
  "query": {
    "multi_match": {
      "query": "搜索值",
      "fields": [
        "搜索的字段1","搜索的字段2"]
    }
  }
}
  • multi_phrase, 短语搜索, 不会吧搜索值拆开来搜索:

{
  "query": {
    "match_phrase": {
      "字段": "搜索值"
    }
  }
}
  • _source, 字段过滤, 查询的结果只显示指定字段:

{
  "query": {
    "查询条件"
  },
  "_source": [
    "显示的字段1",
    "显示的字段2"
    ]
}
  • highlights, 高亮查询, 根据查询的关键字来进行高亮, 高亮的结果会显示在返回结果中的 highlight 中, 关键字会被加上<em>标签, 如果想要多字段高亮,也需要进行多字段搜索:

{
  "query": {
    "查询条件"
  },
  "highlight": {
    "fields": {
      "高亮的字段名1": {}
    }
  }
}

由于对多个字段使用不同搜索值涉及条件拼接, 所以单独讲.

前置知识讲解: 对于条件拼接, 在SQL中有 and, or, not, 在ElasticSearch不太一样, 下面逐一讲解:

  • bool: 用来表明里面的语句是多条件的组合, 用来包裹多个条件.

  • should: 里面可以有多个条件, 查询结果必须符合查询条件中的一个或多个.

  • must: 里面的多个条件都必须成立.

  • must_not: 里面的多个条件必须不成立.

1.3.2 过滤 Filter

过滤的效果其实有点像条件搜索,不过条件搜索会考虑相关度分数和考虑分词,而过滤是不考虑这些的,过滤对相关度没有影响。过滤一般用于结构化的数据上,也就是通常不用于使用了分词的数据上,通常都会用在数值类型和日期类型的数据上。

在搜索的时候,如果你不希望要搜索的条件会影响到相关度,那么就把它放在过滤中,如果希望影响相关度,那么就放在条件搜索中。 使用过滤时,由于不考虑相关度,所以score固定为1。

文档的过滤filter里面主要有五种字段,range,term,terms,exist,missing。range用于字段数据比较大小;term主要用于比较字符类型的和数值类型的数据是否相等;terms是term的复数版,里面可以有多个用于比较相等的值;exist和missing用于判断文档中是否包含指定字段或没有某个字段(仅适用于2.0+版本,目前已经移除)

1.3.3 聚合 Aggregate

Links:

和 SQL 中的 SUM, MAX, MIN 函数类似, ES 也提供了很多聚合函数, 总体而言分三大类:

  • Metric: 对某个 Field 的值做计算, 例如 Average, Min, Max 都属于这一类

  • Bucket: 按照值将文档放入不同的 Bucket 中, 和 SQL 中的 GroupBy 类似

  • Pipeline: 对多个 Aggregation 进行嵌套所形成的管道