Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎。

ES 介绍

玩“飞花令”游戏时,让游戏参与者说出带“月”字的诗句,我们可以去百度输入“带月字的古诗”, 百度就会返回相关的信息。

ES 也是一个类似的搜索引擎,它的作用就是从海量的数据中找到我们所关心的问题,如:

  • 带月字的古诗?
  • 24 小时内带 connection lost 关键字的日志?
  • 某个产品包含卡顿关键字的用户评论?

ES 也能处理数据聚合的问题,如:

  • 包含卡顿关键字的用户评论的数量?
  • 7天内接口调用的平均耗时,最小耗时,最大耗时?

ES 实现快速查询的关键就是倒排索引。

正向索引与倒排索引

如果我们需要查找带月的古诗,首先我们要有数据。

如我们提供两首李白的古诗:

《静夜思》

床前明月光,疑是地上霜。举头望明月,低头思故乡。

 《玉阶怨》唐·李白

  玉阶生白露,夜久侵罗袜。却下水晶帘,玲珑望秋月。

对于一般的数据库,我们常常会把诗名作为索引的键,内容作为值。

这种情况下如果我们查询“静夜思”对应的内容是非常快的。

但是查询带月的诗就慢得多,需要先找到所有诗的内容,然后找其中是否有月。 想要快速查询,可以建立一个以“月”为键,诗名为值的索引。

keyvalue
静夜思
静夜思
静夜思
静夜思 玉阶怨

如果我们查找带月的古诗就能快速找到“静夜思 玉阶怨” ,然后再根据正向索引就能找到内容。

以内容作为键的索引就叫做倒排索引,也叫反向索引。

搜索引擎的核心就是建立倒排索引。

ES 系统

ES 是基于 Apache Lucene ,Lucene 可以看是一个建立倒排索引的库。ES 基于 Lucence 封装, 实现了分布式的搜索引擎,并且所有的操作都提供 rest api。

ES中的重要概念

在使用 ES 之前,需要先了解以下 ES 中的几个重要概念。

索引库 indices

索引库类似与 mysql 中库(database)的概念,indices 是 index 的复数,意思是有许多索引。

文档 Document

文档就是存入索引中的原始数据,每一条信息就是一个文档。ES 中的文档格式都是 json, 每个文档都是一个 json 对象。

字段 field

文档中的属性,一个文档中可以有多个属性,如:

1
2
3
4
{
    "user_name": "123",
    "user_password": "111"
}

上面这个文档包括 user_nameuser_password

字段数据类型

每个字段都有它的数据类型,如 string 类型,boolean 类型。类型指示字段的数据 类型及索引动作对字段的操作。

例如一个字符串可以为 text 类型,也可以为 keyword 类型。text 类型是为了全文搜索, keyword 类型是为了索引和排序。在创建字段时需要根据用途选择类型。

所有的数据类型:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

映射 Mapping

映射是定义文档及其包含的字段如何存储和索引的过程。

文档中的每个字段都有它们的数据类型,Mapping 可以定义字段的类型及其它的一些属性。

如:

1
2
3
4
5
6
7
8
9
{
  "mappings": {
    "properties": {
      "user_name": {
        "type":  "keyword"
      }
    }
  }
}

上面的 mapping 定义了属性 user_name 的类型为 keyword

索引模板 Index Template

索引模块定义了索引的相关设置(setting)和映射(Mapping),当创建一个新的索引时直接应用模板快速创建。

搜索

搜索就是将我们的问题以 ES 能够理解的方式向 ES 发出请求,ES 会返回对应的数据, 如:

  • 找出所有带月的诗句

查询 DSL

一个搜索可以分解成多个查询,要想 ES 能够理解查询请求,就得用 ES 的查询 DSL。

比如下面的查询意思就是 verse 字段中有月的数据

1
2
3
4
5
6
7
{
  "query": {
    "match": {
      "verse": "月"
    }
  }
}

聚合 Aggregations

聚合操作可以将 ES 中的数据进行统计或度量,如:

  • 网站的平均加载时间
  • 带月的古诗的数量

这里只是简单介绍,更多的内容可以看官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

ES 实战

ES 是一个比较复杂的分布式系统,但是我们可以在自己的PC上体验它的功能。

安装 ES

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html

Windows 就是下载一个压缩包,解压后执行 .\bin\elasticsearch.bat 启动 ES。

ES 服务的默认端口为 9200 ,ES 启动后就可以用 rest api 使用 ES。

创建索引

下面创建一个索引来保存古诗。

PUT http://127.0.0.1:9200/poetry
Content-Type: application/json
{
    "mappings":
    {
        "properties":
        {
            "poetry_name" : { "type" : "keyword" },
            "poetry_content" : { "type" : "text" }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "poetry"
}
// PUT http://127.0.0.1:9200/poetry
// HTTP/1.1 200 OK
// X-elastic-product: Elasticsearch
// Warning: 299 Elasticsearch-7.15.0-79d65f6e357953a5b3cbcc5e2c7c21073d89aa29 "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security."
// content-type: application/json; charset=UTF-8
// content-length: 73
// Request duration: 0.267371s

它有两个字段,poetry_name 表示诗名,类型为 keyword,poetry_content 表示诗内容,类型为 text

增加文档

一个文档即一条记录,下面向索引中添加文档

POST http://127.0.0.1:9200/poetry/_doc/
Content-Type: application/json
{
    "poetry_name" : "静夜思",
    "poetry_content" : "床前明月光,疑是地上霜。举头望明月,低头思故乡。"
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "_index": "poetry",
  "_type": "_doc",
  "_id": "GzyMfnwBkpjcizGoE2rW",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}
// POST http://127.0.0.1:9200/poetry/_doc/
// HTTP/1.1 201 Created
// Location: /poetry/_doc/GzyMfnwBkpjcizGoE2rW
// X-elastic-product: Elasticsearch
// Warning: 299 Elasticsearch-7.15.0-79d65f6e357953a5b3cbcc5e2c7c21073d89aa29 "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security."
// content-type: application/json; charset=UTF-8
// content-length: 173
// Request duration: 0.010882s
POST http://127.0.0.1:9200/poetry/_doc/
Content-Type: application/json
{
    "poetry_name" : "玉阶怨",
    "poetry_content" : "玉阶生白露,夜久侵罗袜。却下水晶帘,玲珑望秋月。"
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "_index": "poetry",
  "_type": "_doc",
  "_id": "HDyMfnwBkpjcizGoPmpr",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}
// POST http://127.0.0.1:9200/poetry/_doc/
// HTTP/1.1 201 Created
// Location: /poetry/_doc/HDyMfnwBkpjcizGoPmpr
// X-elastic-product: Elasticsearch
// Warning: 299 Elasticsearch-7.15.0-79d65f6e357953a5b3cbcc5e2c7c21073d89aa29 "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security."
// content-type: application/json; charset=UTF-8
// content-length: 173
// Request duration: 0.010298s

查询带月的诗

GET http://127.0.0.1:9200/poetry/_search/
Content-Type: application/json
{
    "query" :
    {
        "term" :
        {
            "poetry_content" :
            {
                "value" : "月"
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
  "took": 156,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.25069216,
    "hits": [
      {
        "_index": "poetry",
        "_type": "_doc",
        "_id": "GzyMfnwBkpjcizGoE2rW",
        "_score": 0.25069216,
        "_source": {
          "poetry_name": "静夜思",
          "poetry_content": "床前明月光,疑是地上霜。举头望明月,低头思故乡。"
        }
      },
      {
        "_index": "poetry",
        "_type": "_doc",
        "_id": "HDyMfnwBkpjcizGoPmpr",
        "_score": 0.18232156,
        "_source": {
          "poetry_name": "玉阶怨",
          "poetry_content": "玉阶生白露,夜久侵罗袜。却下水晶帘,玲珑望秋月。"
        }
      }
    ]
  }
}
// GET http://127.0.0.1:9200/poetry/_search/
// HTTP/1.1 200 OK
// X-elastic-product: Elasticsearch
// Warning: 299 Elasticsearch-7.15.0-79d65f6e357953a5b3cbcc5e2c7c21073d89aa29 "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security."
// content-type: application/json; charset=UTF-8
// content-length: 625
// Request duration: 0.161839s

带月的诗的数量

GET http://127.0.0.1:9200/poetry/_count/
Content-Type: application/json
{
    "query" :
    {
        "term" :
        {
            "poetry_content" :
            {
                "value" : "月"
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "count": 2,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  }
}
// GET http://127.0.0.1:9200/poetry/_count/
// HTTP/1.1 200 OK
// X-elastic-product: Elasticsearch
// Warning: 299 Elasticsearch-7.15.0-79d65f6e357953a5b3cbcc5e2c7c21073d89aa29 "Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security."
// content-type: application/json; charset=UTF-8
// content-length: 71
// Request duration: 0.006464s

参考链接:

https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

https://zhuanlan.zhihu.com/p/62892586