Elasticsearch 初探

Elasticsearch 是一个开源分布式全文搜索引擎。它建立在当前最先进有效的搜索引擎库 Lucene 之上。Elasticsearch 集成了 Lucene 的检索功能,并通过一套简单的 API 隐藏了 Lucene 的复杂性,使之简单易用。

初识


ES 的初步介绍

本节将介绍 ES 的几个特性。这些介绍能帮助我们理解 ES 是应什么需求诞生的?它解决了什么问题?它为何如此架构?以及这种架构方式为它带来哪些性能上的提升?这些信息虽然不能直接提升我们使用 ES 的能力,但能从更深的维度帮助我们使用好它。

不仅仅是搜索

ES 不仅能够搜索,它还提供一套分布式实时存储文档的解决方案。 ES 允许用户将数据存储在多个服务器节点上。这些节点能实时共享数据。一旦主节点的内容发生改变,这些改变会实时传递到副节点上,以保证主副节点的内容一致。如果主节点掉线,ES 能立即选举出一个副节点充当主节点。选举过程就像切换开关一样,能够在瞬间完成,从而保证了 ES 的可靠性。

分布式的存储方案不仅仅是基于数据安全的考量,同时也是为了加快检索的速度。利用 MapReduce,ES 可以在多个节点上并行地检索数据,大大缩短了海量数据处理的时间。

领域专用语言

为了统一查询语法,ES 设计了一套领域专用语言 (DSL, domain specific language)。这套语言基于 JSON,优点是简单易学,缺点是在表达复杂的查询时,会显得格外冗长,阅读起来也不太友好。

SQL 和 NoSQL

SQL 全称 Structured Query Language。SQL 中的 Structured 突出了它是结构化的查询语言。结构化即受字段限制。SQL 数据库中的每条数据都具有相同的长度,因此可以被视作一张数据表。相比于 SQL,NoSQL 能表达更复杂的内部数据结构。字段之间不相互影响,可以拥有各自的层级结构。因此 NoSQL 数据库要比 SQL 数据库更加灵活且易于拓展。NoSQL 数据库中的数据通常用 JSON 表示。

入门


一些简单概念

文档

在 ES 中,文档是一个特定的术语。它表示用来存储对象的存储单元。一个对象通常不会是简单的键值对,它可能包含更复杂的数据结构,比如日期、地理数据、数组等。为表达这种复杂的、多层次的数据,ES 将 JSON 作为文档存储的固定格式。也就是说在 ES 里,一个文档被存成一个 JSON 值。

一个文档必须包含三个元数据

  • _index:文档在哪存放
  • _type:文档表示的对象类别
  • _id:文档的唯一标识

文档中的其他字段,则可以视需求定义。

请求

一个个文档存在于 ES 中,如果我们想要查询、添加、删除、更新某个文档,那么我们就必须向 ES 发送请求。

一个 Elasticsearch 请求由以下部件组成:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
部件 用途
<VERB> 操作数据的方法,常见的有查询(GET)、上传(POST)、更新(PUT)
<PROTOCOL> http 或者 https
<HOST> 主机名
<PORT> HTTP 服务端口,默认是 9200
<PATH> 文档路径,由_index, _type, _id组成
<QUERY_STRING> 查询参数,?pretty 可以输出格式化的 JSON 值
<BODY> JSON 请求体

实践


君 ES 本当上手

安装与运行

  1. 首先打开https://www.elastic.co/downloads/elasticsearch,下载操作系统对应版本的 ES。

  2. 解压下载的文件,将解压出的文件夹放在你希望的目录下。

  3. 打开 Terminal (MacOS) 或者 PowerShell (Windows),将当前目录切换到放解压文件夹的目录,然后运行:

cd elasticsearch-7.4.0
cd bin
./elasticsearch

这将在当前 Terminal 窗口运行 ES。如果你不希望 ES 服务中止,请勿关闭窗口。

  1. 另外打开一个新的 Terminal 窗口,运行:
curl 'http://localhost:9200/?pretty'

如果 ES 正常运行,终端将会返回一条包含集群信息的 JSON 值。

Note: 更多有关安装的信息,参见 安装并运行 ElasticsearchHow to install Elasticsearch on MacOS

客户端

搭建好 ES 之后,我们还需要与 ES 交互。既然要交互,那么就有客户端和服务端。在生产环境中,服务端往往已经在服务器上搭好。这种情况下,我们只需要配置本地客户端就可以了。

ES 支持多种客户端语言,比如 Java, Ruby, Python。这些语言都有相应的 ES 库,我们可以依据自己的喜好选择。下面主要介绍如何在 Python 环境下搭建 ES 客户端。

  1. 首先确保你已经安装了 Python 及 Python 相关依赖。

  2. 安装 Elasticsearch

pip install elasticsearch
  1. 新建一个 .py 文件。
touch my_es.py
  1. 在你喜欢的 IDE 里打开它,输入以下内容,这将初始化一个名为 es 的客户端。
# 初始化 ES 客户端
import elasticsearch


def init_es_client():
    es = elasticsearch.Elasticsearch(
        hosts="[YOUR-HOST-NAME]", http_auth=("[YOUR-ACCOUNT]", "[YOUR-PASSWORD]")
    )

    return es

es = init_es_client()
  1. 为测试客户端是否搭建成功,可以 print 一下客户端信息。在前文代码之后加上:
print(es.info())

运行 my_es.py,如果收到一条包含 name, cluster_name 等字段的 JSON 返回值,那么恭喜你已经搭建成功了。

客户端请求

搭完客户端,我们就可以向 ES 发送请求了。下面这个函数就是一个查询请求。其中 body 里的内容是请求体,它用 DSL 语法写成。

def search(es_client, start, end):
    result = es_client.search(index="[YOUR-INDEX]", body={
        "query": {
            "bool": {
                "must":[
                    { "range": { "[YOUR-DATE]":{ "gte": start, "lte": end }}}, 
                    {
                        "bool": {
                            "should": [
                                { "match_phrase": { "[YOUR-CONTENT]": "[KEYWORD-1]"}},
                                { "match_phrase": { "[YOUR-CONTENT]": "[KEYWORD-2]"}}
                            ]
                        }
                    }
                ]
            }
        }
    })
    return result

收到这段请求,服务端将返回同时符合以下两个条件的数据:

  1. 时间字段的值的范围在 startend 之间
  2. 内容字段的值包含短语 [KEYWORD-1][KEYWORD-2]

通过请求拿到数据,就到了你大展身手的时候啦!

你可以进一步筛选数据、分析数据;也可以用各种可视化库绘制图表;甚至可以上一些 NLP 的手段训练模型。大门已经开启,一切随你心意。

祝各位玩耍愉快

Note:更多信息参见 ES 官方中文教程