Elasticsearch (ES) 教程:从安装到高级搜索

Elasticsearch (ES) 教程:从安装到高级搜索

Elasticsearch(简称 ES)是一个基于 Apache Lucene 的开源、分布式、RESTful 风格的搜索和数据分析引擎。它能够近实时地存储、搜索和分析海量数据。Elasticsearch 以其高性能、可扩展性和易用性而闻名,广泛应用于日志分析、全文搜索、安全情报、业务分析和基础设施监控等领域。

本教程将带你从零开始,逐步深入了解 Elasticsearch,涵盖安装、配置、基本概念、数据操作、各种搜索技术以及高级特性。

1. 安装与配置

1.1. 环境准备

  • Java 环境: Elasticsearch 需要 Java 8 或更高版本。 建议使用 OpenJDK 或 Oracle JDK。 确保 JAVA_HOME 环境变量已正确设置。
  • 操作系统: Elasticsearch 支持 Linux、macOS 和 Windows。 本教程主要以 Linux (例如 Ubuntu) 为例,其他操作系统上的安装过程类似。
  • 下载: 从官网下载地址进行下载: https://www.elastic.co/cn/downloads/elasticsearch

1.2. 安装步骤 (Linux)

  1. 下载 Elasticsearch:
    bash
    wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.x.x-linux-x86_64.tar.gz (替换为最新版本)

  2. 解压:
    bash
    tar -xzf elasticsearch-8.x.x-linux-x86_64.tar.gz

  3. 进入目录:
    bash
    cd elasticsearch-8.x.x

  4. 启动 Elasticsearch:
    bash
    ./bin/elasticsearch

    第一次启动会生成密码, 务必记下来.

  5. 后台运行(可选):
    bash
    ./bin/elasticsearch -d

  6. 验证安装:
    在浏览器中访问 http://localhost:9200,你应该会看到一个 JSON 响应,其中包含 Elasticsearch 集群的信息。

1.3. 基本配置 (elasticsearch.yml)

Elasticsearch 的主要配置文件是 config/elasticsearch.yml。以下是一些常见的配置项:

  • cluster.name: 集群名称,同一集群中的节点应具有相同的名称。
  • node.name: 节点名称,默认为机器的主机名。
  • path.data: 数据存储路径,默认为 data 目录。
  • path.logs: 日志存储路径,默认为 logs 目录。
  • network.host: 绑定的 IP 地址,默认为 127.0.0.1 (仅本地访问)。要允许远程访问,可以设置为 0.0.0.0
  • http.port: HTTP 端口,默认为 9200
  • discovery.seed_hosts: 集群发现的主机列表 (用于多节点集群)。例如:["192.168.1.10", "192.168.1.11"]
  • cluster.initial_master_nodes: 初始主节点列表 (用于多节点集群)。例如:["node-1", "node-2"]

重要提示: 修改配置文件后,需要重启 Elasticsearch 才能生效。

1.4. 安装 Kibana (可选)

Kibana 是 Elasticsearch 的一个配套工具,提供了一个强大的 Web 界面,用于数据可视化、探索、管理和监控 Elasticsearch 集群。

  1. 下载 Kibana:
    bash
    wget https://artifacts.elastic.co/downloads/kibana/kibana-8.x.x-linux-x86_64.tar.gz (替换为最新版本, 且与 ES 版本对应)

  2. 解压:
    bash
    tar -xzf kibana-8.x.x-linux-x86_64.tar.gz

  3. 进入目录:
    bash
    cd kibana-8.x.x

  4. 启动 Kibana
    bash
    ./bin/kibana

  5. 访问 Kibana:
    在浏览器中访问 http://localhost:5601

2. 核心概念

在深入使用 Elasticsearch 之前,理解以下核心概念至关重要:

  • 集群 (Cluster): 一个或多个 Elasticsearch 节点组成的集合,共同存储和处理数据。
  • 节点 (Node): 一个 Elasticsearch 实例,通常运行在一台服务器上。
  • 索引 (Index): 类似于关系型数据库中的“数据库”,用于存储相关的文档。索引是文档的集合。
  • 类型 (Type): 在 Elasticsearch 7.x 及之前的版本中,类型用于对索引中的文档进行逻辑分组 (类似于数据库中的“表”)。从 Elasticsearch 8.x 开始,类型已被移除。
  • 文档 (Document): Elasticsearch 中存储的基本数据单元,以 JSON 格式表示。类似于关系型数据库中的“行”。
  • 字段 (Field): 文档中的一个属性,包含名称和值。类似于关系型数据库中的“列”。
  • 映射 (Mapping): 定义了索引中字段的类型、存储方式和分析方式。类似于关系型数据库中的“表结构”。
  • 分片 (Shard): 索引可以被水平分割成多个分片,每个分片都是一个独立的 Lucene 索引。分片可以提高性能和可扩展性。
  • 副本 (Replica): 每个分片可以有零个或多个副本。副本可以提高可用性和搜索性能。

3. 数据操作 (CRUD)

Elasticsearch 提供了 RESTful API 来进行各种数据操作,包括创建、读取、更新和删除文档 (CRUD)。

3.1. 创建索引

json
PUT /my_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"title": { "type": "text" },
"content": { "type": "text" },
"timestamp": { "type": "date" }
}
}
}

  • PUT /my_index: 创建名为 my_index 的索引。
  • settings: 索引设置,包括分片数和副本数。
  • mappings: 定义字段的映射。
  • properties: 字段列表。
    • type: 字段类型 (例如 text, keyword, date, integer, boolean 等)。

3.2. 插入文档 (索引文档)

```json
POST /my_index/_doc/1
{
"title": "Elasticsearch Tutorial",
"content": "This is a comprehensive guide to Elasticsearch.",
"timestamp": "2023-10-27T10:00:00"
}

POST /my_index/_doc
{
"title": "Another Document",
"content": "This is another document in the index.",
"timestamp": "2023-10-27T11:00:00"
}
```

  • POST /my_index/_doc/1: 向 my_index 索引添加一个文档,指定 ID 为 1
  • POST /my_index/_doc: 向 my_index 索引添加一个文档,Elasticsearch 会自动生成一个唯一的 ID。

3.3. 获取文档

json
GET /my_index/_doc/1

  • GET /my_index/_doc/1: 获取 my_index 索引中 ID 为 1 的文档。

3.4. 更新文档

json
POST /my_index/_update/1
{
"doc": {
"content": "This is an updated guide to Elasticsearch."
}
}

  • POST /my_index/_update/1 更新 ID 为1 的文档
  • doc: 包含要更新的字段。

3.5. 删除文档

json
DELETE /my_index/_doc/1

  • DELETE /my_index/_doc/1: 删除 my_index 索引中 ID 为 1 的文档。

3.6. 删除索引

json
DELETE /my_index

* DELETE /my_index: 删除名为 my_index 的索引。

4. 搜索

Elasticsearch 的核心功能是搜索。它提供了强大的查询 DSL (Domain Specific Language),允许你构建各种复杂的查询。

4.1. 基本搜索

json
GET /my_index/_search
{
"query": {
"match_all": {}
}
}

  • match_all: 匹配所有文档。

json
GET /my_index/_search
{
"query": {
"match": {
"content": "guide"
}
}
}

  • match: 在 content 字段中搜索包含 "guide" 的文档。

4.2. 常用查询类型

  • term 查询: 精确匹配,不进行分词。
    json
    {
    "query": {
    "term": {
    "title.keyword": "Elasticsearch Tutorial"
    }
    }
    }

  • terms 查询: 匹配多个精确值。
    json
    {
    "query": {
    "terms": {
    "tags": ["elasticsearch", "tutorial"]
    }
    }
    }

  • range 查询: 范围查询。
    json
    {
    "query": {
    "range": {
    "timestamp": {
    "gte": "2023-10-27T00:00:00",
    "lte": "2023-10-27T23:59:59"
    }
    }
    }
    }

  • exists 查询: 检查字段是否存在。
    json
    {
    "query": {
    "exists": {
    "field": "author"
    }
    }
    }

  • bool 查询: 组合多个查询。
    json
    {
    "query": {
    "bool": {
    "must": [
    { "match": { "title": "elasticsearch" } },
    { "match": { "content": "tutorial" } }
    ],
    "must_not": [
    { "term": { "status": "draft" } }
    ],
    "should": [
    { "term": { "featured": true } }
    ],
    "filter": {
    "range": {
    "timestamp": {
    "gte": "now-1d/d"
    }
    }
    }
    }
    }
    }

    • must: 必须匹配(AND)。
    • must_not: 必须不匹配 (NOT)。
    • should: 应该匹配 (OR),可以提高相关性得分。
    • filter: 过滤,不参与算分.
  • wildcard 查询: 通配符查询,* 代表多个字符, ?代表一个字符
    json
    {
    "query": {
    "wildcard": {
    "user.id": {
    "value": "ki*y",
    "boost": 1.0,
    "rewrite": "constant_score"
    }
    }
    }
    }

4.3. 过滤 (Filter)

过滤与查询类似,但不计算相关性得分,因此执行速度更快。过滤通常用于结构化数据的筛选。

json
GET /my_index/_search
{
"query": {
"bool": {
"must": {
"match": { "content": "guide" }
},
"filter": {
"term": { "status": "published" }
}
}
}
}

在上面的例子, filter 不会影响搜索结果的排序。

4.4. 排序 (Sorting)

json
GET /my_index/_search
{
"query": {
"match_all": {}
},
"sort": [
{ "timestamp": { "order": "desc" } }
]
}

  • sort: 指定排序字段和顺序 (ascdesc)。

4.5. 分页 (Pagination)

json
GET /my_index/_search
{
"query": {
"match_all": {}
},
"from": 10,
"size": 20
}

  • from: 起始位置 (偏移量)。
  • size: 返回的文档数量。

4.6 全文检索

Elasticsearch 基于 Lucene 的倒排索引,对全文检索有非常好的支持。以下是全文检索中常用的概念:

  • 分词 (Analysis): 将文本分解成一系列的词条 (terms) 的过程。Elasticsearch 内置了多种分词器,也可以自定义分词器。
  • 词干提取 (Stemming): 将单词还原为词根形式 (例如,"running" -> "run")。
  • 停用词 (Stop words): 常见的、无实际意义的词 (例如,"the", "a", "is"),通常在索引和搜索时会被忽略。

5. 高级特性

5.1. 聚合 (Aggregations)

聚合用于对数据进行统计和分析。Elasticsearch 提供了多种聚合类型,例如:

  • terms 聚合: 按字段值分组。
  • avg 聚合: 计算平均值。
  • sum 聚合: 计算总和。
  • min 聚合: 计算最小值。
  • max 聚合: 计算最大值。
  • date_histogram 聚合: 按日期范围分组。

json
GET /my_index/_search
{
"size": 0,
"aggs": {
"group_by_status": {
"terms": {
"field": "status.keyword"
}
},
"average_price": {
"avg": {
"field": "price"
}
}
}
}

上面例子中, size:0 表示不返回文档本身, aggs定义了两个聚合.

5.2. 索引别名 (Aliases)

索引别名可以指向一个或多个索引,类似于数据库中的视图。别名可以简化索引管理,实现零停机时间的数据迁移和索引重建。

json
POST /_aliases
{
"actions": [
{ "add": { "index": "my_index_v1", "alias": "my_index" } },
{ "remove": { "index": "my_index_v1", "alias": "my_old_index" } }
]
}

5.3. 滚动查询

对于需要检索大量数据的场景,可以使用滚动查询(Scroll API)。滚动查询会创建一个快照,并允许你分批次地获取结果。

json
GET /my_index/_search?scroll=1m
{
"size": 100,
"query": {
"match_all" : {}
}
}

首次查询后, 会得到一个 _scroll_id, 使用 _scroll_id 进行后续查询:

json
POST /_search/scroll
{
"scroll" : "1m",
"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
}

5.4 批量操作

为了提高效率, 可以使用批量操作, 一次执行多个请求。

```json
POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }

```

6. 总结

本教程详细介绍了 Elasticsearch 的安装、配置、核心概念、数据操作、搜索技术和高级特性。 通过学习本教程,你应该能够:

  • 安装和配置 Elasticsearch。
  • 理解 Elasticsearch 的核心概念。
  • 使用 RESTful API 进行数据操作。
  • 构建各种类型的查询。
  • 使用聚合进行数据分析。
  • 了解并运用一些高级功能。

Elasticsearch 是一个功能强大且灵活的工具,可以应用于各种场景。 随着你对 Elasticsearch 的深入了解和实践,你将能够更好地利用它来解决实际问题。 建议进一步阅读 Elasticsearch 官方文档,并进行更多的实践操作,以掌握更高级的用法和技巧。

THE END