Elasticsearch 快速入门教程 – wiki基地


Elasticsearch 快速入门教程:从零开始探索强大的搜索引擎

前言

在当今爆炸式增长的数据时代,如何高效地存储、搜索和分析海量数据成为了一个核心挑战。无论是网站搜索、日志分析、监控告警,还是实时数据可视化,传统的数据库系统往往难以满足需求。正是在这样的背景下,Elasticsearch 应运而生,并迅速成为了分布式搜索和分析领域的领导者。

Elasticsearch(简称ES)是一个高度可扩展的开源全文本搜索和分析引擎。它基于 Apache Lucene 构建,隐藏了 Lucene 的复杂性,提供了一个简单易用的 RESTful API 接口。凭借其出色的速度、可伸缩性和灵活性,Elasticsearch 被广泛应用于各种场景。

本篇教程旨在帮助完全没有Elasticsearch经验的初学者,快速掌握其核心概念、安装部署以及基本操作。通过阅读本文,你将能够理解Elasticsearch的工作原理,搭建自己的本地环境,并进行文档的索引、检索、更新和删除等基本操作。

由于篇幅和入门定位的限制,本文将聚焦于Elasticsearch的核心基础,对于集群管理、性能优化、安全配置等高级主题将仅作简要提及或留待后续深入学习。

预计学习目标:

  1. 理解 Elasticsearch 是什么以及它为什么如此流行。
  2. 掌握 Elasticsearch 的核心概念(文档、索引、分片、副本等)。
  3. 学会在本地安装和启动 Elasticsearch。
  4. 学会使用 Kibana 的 Dev Tools 或 cURL 与 Elasticsearch 进行交互。
  5. 掌握文档的索引(添加)、获取、更新和删除等基本操作。
  6. 学习如何执行简单的搜索查询。
  7. 了解 Elasticsearch 的基本架构和优势。

让我们开始Elasticsearch的探索之旅吧!

第一章:Elasticsearch 核心概念解析

在深入实践之前,理解Elasticsearch的一些核心概念至关重要。这些概念构成了Elasticsearch的基础,有助于你更好地理解后续的操作。

1. 文档 (Document)

文档是 Elasticsearch 中最小的数据单元。你可以把它想象成关系型数据库中的一行记录,或者一个JSON对象。在 Elasticsearch 中,数据以JSON格式存储和传输。

一个文档可以包含多种类型的数据,如字符串、数字、布尔值、日期、嵌套对象等。每个文档都有一个唯一的ID(可以在索引时指定,或由Elasticsearch自动生成)以及它所属的索引

示例文档 (JSON):

json
{
"title": "Elasticsearch Quick Start Guide",
"author": "Your Name",
"publish_date": "2023-10-27",
"tags": ["elasticsearch", "tutorial", "search"],
"content": "This article helps you quickly get started with Elasticsearch...",
"views": 150
}

2. 索引 (Index)

索引是 Elasticsearch 中存储相似文档的逻辑集合。你可以把它类比为关系型数据库中的一个“数据库”或“表”(尽管这种类比不完全准确,但有助于理解)。

一个索引定义了其中文档的映射 (Mapping),即文档中各个字段的数据类型、如何被分析(用于全文搜索)以及如何存储等信息。Elasticsearch 是一个Schema-less 的系统,这意味着你在索引文档时,如果没有预先定义 Mapping,Elasticsearch 会尝试根据文档内容自动创建 Mapping (Dynamic Mapping)。但这在实际应用中通常需要手动精确控制 Mapping,以确保搜索和分析的准确性。

重要特性:

  • 逻辑隔离: 不同索引之间的数据是相互独立的。
  • 可扩展性: 一个索引可以分布在多个节点上。
  • 优化: 索引级别的设置(如分片数、副本数)对性能和可用性至关重要。

3. 类型 (Type) – 已废弃

在 Elasticsearch 7.0.0 版本之前,一个索引可以包含多个类型 (Type)。类型类似于关系型数据库中“表”的概念,用于区分索引中不同结构的文档。例如,一个博客索引可能包含 “post” 类型和 “comment” 类型。

重要提示: 从 Elasticsearch 7.0.0 开始,类型已被移除。 一个索引只能包含一种类型的文档。现有的应用在升级到新版本时需要进行数据迁移和结构调整。在本教程中,我们将遵循最新版本的约定,不再使用 Type。

4. 映射 (Mapping)

映射定义了索引中文档的结构和字段的数据类型,以及这些字段如何被索引和搜索。它是实现精确搜索和分析的基础。

核心作用:

  • 数据类型: 明确每个字段的数据类型(如 text, keyword, long, double, boolean, date, object, nested 等)。
  • 分析器 (Analyzer): 对于文本字段,指定如何进行分词、标准化(如转小写、去除停用词)等处理,以实现全文搜索。text 字段会被分析,而 keyword 字段不会被分析,适合用于精确匹配、排序和聚合。
  • 索引选项: 控制字段是否可被搜索、是否存储原始值等。

你可以手动创建带有特定 Mapping 的索引,也可以让 Elasticsearch 根据第一个文档的内容自动生成 Mapping。手动定义 Mapping 通常是更好的做法,特别是对于文本字段的分析器选择。

5. 字段 (Field)

文档中的每个键值对就是一个字段。例如,在上面的文档示例中,title, author, publish_date 等都是字段。

6. 集群 (Cluster)

一个集群由一个或多个 Elasticsearch 节点组成,它们共同存储所有的数据,并提供跨所有节点的索引和搜索能力。集群提供了分布式、高可用和可伸缩性。

7. 节点 (Node)

节点是运行 Elasticsearch 实例的服务器。一个节点是集群的一部分,存储数据,参与集群的索引和搜索功能。节点可以配置为不同的角色(如 Master 节点负责集群管理,Data 节点负责数据存储和搜索,Ingest 节点负责数据预处理等)。在快速入门时,通常从单个节点开始。

8. 分片 (Shard)

索引可以被水平分割成多个分片 (Shard)。每个分片都是一个独立的 Lucene 索引实例,包含索引数据的一部分。

为什么需要分片?

  • 解决单个节点存储限制: 单个节点的磁盘容量、内存或CPU能力可能不足以处理大规模数据。通过分片,可以将一个大索引分布到多个节点上。
  • 提高吞吐量: 分片允许在多个节点上并行执行索引和搜索操作,从而提高性能。

创建索引时,你可以指定主分片的数量 (number_of_shards)。一旦索引创建,主分片数量不能修改。

9. 副本 (Replica)

副本是主分片的复制。每个主分片可以有零个或多个副本。副本也存储在不同的节点上(通常是不同于主分片所在的节点)。

为什么需要副本?

  • 高可用性: 如果主分片所在的节点宕机,副本分片可以提升为新的主分片,确保数据不丢失和服务的连续性。
  • 提高搜索吞吐量: 搜索请求可以由主分片或其任何副本处理,从而分担负载,提高搜索性能。

创建索引时,你可以指定副本分片的数量 (number_of_replicas)。副本数量可以在索引创建后动态调整。

一个健康的 Elasticsearch 集群通常至少需要两个节点(以放置主分片和副本分片),并为每个主分片配置至少一个副本(number_of_replicas: 1),以实现高可用。

概念总结关系图:

Cluster (集群)
└── Nodes (节点)
└── Indices (索引)
└── Shards (分片 - Primary 主要用于索引,Replica 用于高可用和搜索)
└── Documents (文档 - JSON 格式)
└── Fields (字段)

理解了这些核心概念,我们就具备了进行下一步实践的基础。

第二章:安装与启动 Elasticsearch 和 Kibana

开始使用 Elasticsearch 的第一步是在你的本地环境搭建起一个可用的实例。最简单的方式是直接下载并运行官方提供的二进制文件。我们还会同时安装 Kibana,它是 Elasticsearch 的官方可视化工具,对于开发、管理和查询非常方便。

1. 环境要求

  • Java Development Kit (JDK): Elasticsearch 需要 Java 运行环境。请确保你的系统安装了 OpenJDK 或 Oracle JDK 11 或更高版本。可以从 Adoptium (Temurin) 或 Oracle 官网下载。安装后,设置好 JAVA_HOME 环境变量。
  • 足够的内存和磁盘空间: 即使是入门,也建议分配至少 2GB 内存给 Elasticsearch,并确保有足够的磁盘空间来存储数据。

2. 下载 Elasticsearch 和 Kibana

访问 Elastic 官方网站下载页面:
* Elasticsearch 下载:https://www.elastic.co/cn/downloads/elasticsearch
* Kibana 下载:https://www.elastic.co/cn/downloads/kibana

请确保下载相同版本的 Elasticsearch 和 Kibana。选择适合你操作系统的版本(例如 .tar.gz for Linux/macOS, .zip for Windows)。

3. 安装步骤 (以 Linux/macOS 为例)

步骤 1:解压文件

将下载的 .tar.gz 文件解压到你选择的目录。

bash
tar -zxvf elasticsearch-x.y.z-linux-x86_64.tar.gz
tar -zxvf kibana-x.y.z-linux-x86_64.tar.gz

x.y.z 替换为你下载的实际版本号。

步骤 2:配置 Elasticsearch (可选但推荐)

进入解压后的 Elasticsearch 目录,找到 config 文件夹,编辑 elasticsearch.yml 文件。

对于本地单节点开发,通常不需要进行复杂的配置。但为了避免可能的网络绑定问题,可以修改 network.host 参数:

“`yaml

修改 config/elasticsearch.yml

network.host: 127.0.0.1
“`

这会将 Elasticsearch 绑定到本地回环地址。

步骤 3:启动 Elasticsearch

进入 Elasticsearch 目录,运行启动脚本:

“`bash

在 Elasticsearch 目录下执行

bin/elasticsearch
“`

Windows 用户运行 bin\elasticsearch.bat

Elasticsearch 会启动并输出大量日志。看到类似 [INFO ... ] cluster.routing.allocation - Cluster health status changed from [RED] to [YELLOW][INFO ... ] cluster.routing.allocation - Cluster health status changed from [YELLOW] to [GREEN] 的日志,表示 Elasticsearch 已经成功启动并加入了一个单节点集群。

默认情况下,Elasticsearch 运行在 http://localhost:9200。你可以在浏览器中访问这个地址,如果看到一个包含版本信息和集群名称的 JSON 响应,说明 Elasticsearch 正在运行。

json
{
"name" : "your_node_name",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "...",
"version" : {
"number" : "x.y.z",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "...",
"build_date" : "...",
"build_snapshot" : false,
"lucene_version" : "...",
"minimum_wire_compatibility_version" : "...",
"minimum_index_compatibility_version" : "..."
},
"tagline" : "You Know, for Search"
}

步骤 4:配置 Kibana

进入解压后的 Kibana 目录,找到 config 文件夹,编辑 kibana.yml 文件。

你需要告诉 Kibana 去连接哪个 Elasticsearch 实例。默认配置通常是连接本地的 Elasticsearch,但最好确认一下:

“`yaml

修改 config/kibana.yml

elasticsearch.hosts: [“http://localhost:9200”]
“`

步骤 5:启动 Kibana

进入 Kibana 目录,运行启动脚本:

“`bash

在 Kibana 目录下执行

bin/kibana
“`

Windows 用户运行 bin\kibana.bat

Kibana 也会输出日志。看到类似 Server running at http://localhost:5601 的日志,表示 Kibana 已经成功启动。

默认情况下,Kibana 运行在 http://localhost:5601。在浏览器中访问这个地址,你应该能看到 Kibana 的登录页面(如果开启了安全认证)或主界面。

4. 使用 Kibana Dev Tools

Kibana Dev Tools 是一个非常实用的工具,它提供了一个控制台界面,可以直接输入和执行 Elasticsearch REST API 请求。这比使用 cURL 命令要方便得多。

在 Kibana 界面中,通常可以在左侧导航栏找到 “Management” -> “Dev Tools”。点击进入后,你会看到一个左边用于输入请求,右边用于显示响应的界面。

接下来的基本操作都将通过 Kibana Dev Tools 来演示。左侧输入框中输入请求,然后点击请求旁边的绿色播放按钮 () 或按 Ctrl/Cmd + Enter 执行。

基本请求格式:

http
METHOD /path/to/api
{
"request_body": "..."
}

例如,获取集群健康状态:

http
GET /_cat/health?v

在左侧输入框输入这行,点击执行,右侧会显示集群的健康信息。

第三章:基本操作:索引、获取、更新、删除文档

现在 Elasticsearch 和 Kibana 都已经运行起来了,我们可以开始进行一些基本的数据操作了。这些操作主要通过 RESTful API 来完成。

1. 查看集群健康状态 (_cat/health)

这是一个常用的 API,用于快速了解集群的健康状况。

请求:

http
GET /_cat/health?v

响应示例:

epoch timestamp cluster status index docs.count docs.deleted active_shards relocating_shards active_primary_shards initializing_shards unassigned_shards pending_tasks max_task_wait_time active_gil_lock duration time_millis
1678886400 10:00:00 elasticsearch green 0 0 0 0 0 0 0 0 0 -1 0b -1 0

status 字段的含义:

  • green: 所有主分片和副本分片都可用,集群健康。
  • yellow: 所有主分片都可用,但至少有一个副本分片不可用。数据仍然完整,但高可用性受影响。
  • red: 至少有一个主分片不可用。部分数据可能无法访问。

在单节点入门环境下,如果看到 yellow 是正常的,因为副本分片无法分配到其他节点上。如果有多个节点且配置了副本,通常会看到 green

2. 查看所有索引 (_cat/indices)

这个 API 可以列出当前集群中的所有索引及其基本信息。

请求:

http
GET /_cat/indices?v

响应示例:

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .kibana_task_manager_x... 1 1 2 0 23.3kb 11.6kb
green open .kibana_x... 1 1 3 0 42.1kb 21kb

.kibana 开头的索引是 Kibana 自己创建和使用的,可以忽略它们。

3. 索引文档 (Index Document)

索引文档就是向 Elasticsearch 中添加数据。你可以指定文档的 ID,也可以让 Elasticsearch 自动生成。

方法一:使用 PUT 指定文档 ID

如果你有数据的唯一标识符,可以使用 PUT 方法。如果 ID 已经存在,会替换掉整个旧文档;如果不存在,则会创建新文档。

请求格式:

http
PUT /<index_name>/_doc/<document_id>
{
"field1": "value1",
"field2": "value2",
...
}

示例:索引一个产品文档到名为 products 的索引,ID 为 1

http
PUT /products/_doc/1
{
"name": "Laptop",
"brand": "Dell",
"price": 1200.50,
"in_stock": true,
"tags": ["electronics", "computer"]
}

响应示例:

json
{
"_index": "products",
"_id": "1",
"_version": 1,
"result": "created", // 或 "updated" 如果是替换旧文档
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}

方法二:使用 POST 让 Elasticsearch 自动生成 ID

如果你没有数据的唯一标识符,可以使用 POST 方法。Elasticsearch 会自动生成一个唯一的 ID。

请求格式:

http
POST /<index_name>/_doc
{
"field1": "value1",
"field2": "value2",
...
}

示例:索引一个订单文档到名为 orders 的索引,自动生成 ID

http
POST /orders/_doc
{
"order_id": "ORD12345",
"customer_name": "Alice",
"amount": 250.75,
"order_date": "2023-10-27T10:30:00Z"
}

响应示例:

json
{
"_index": "orders",
"_id": "AbCdefGhIjKlMnOqrSTu", // 自动生成的 ID
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}

注意:在单节点默认配置下,_shards.total 是主分片数 + 副本分片数 (1主 + 1副 = 2)。successful 是主分片和副本分片都成功写入的数量。

4. 获取文档 (Get Document)

通过文档的 ID 可以获取完整的文档内容。

请求格式:

http
GET /<index_name>/_doc/<document_id>

示例:获取之前索引的产品文档 (ID: 1)

http
GET /products/_doc/1

响应示例:

json
{
"_index": "products",
"_id": "1",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true, // 表示找到了文档
"_source": { // 原始文档内容
"name": "Laptop",
"brand": "Dell",
"price": 1200.50,
"in_stock": true,
"tags": ["electronics", "computer"]
}
}

如果文档不存在,found 字段会是 false,并且没有 _source 字段。

5. 更新文档 (Update Document)

Elasticsearch 中的更新操作实际上是先删除旧文档,再索引一个新文档。但 Elasticsearch 提供了两种更便捷的更新方式:

方法一:全量替换 (使用 PUT)

使用 PUT 方法索引文档时,如果指定了已存在的 ID,会用新的文档完全替换旧文档。

示例:修改产品文档 (ID: 1) 的价格

http
PUT /products/_doc/1
{
"name": "Laptop",
"brand": "Dell",
"price": 1150.00, // 价格变了
"in_stock": true,
"tags": ["electronics", "computer"],
"description": "Powerful laptop for work and play." // 新增字段
}

响应示例:

json
{
"_index": "products",
"_id": "1",
"_version": 2, // 版本号增加
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1, // 序列号增加
"_primary_term": 1
}

可以看到 _version 增加到了 2,resultupdated

方法二:局部更新 (使用 POST + _update endpoint)

通常我们只需要修改文档的某个字段,而不是替换整个文档。这时应该使用 _update 接口。

请求格式:

http
POST /<index_name>/_update/<document_id>
{
"doc": {
"field_to_update1": "new_value1",
"field_to_update2": "new_value2",
...
}
}

示例:再次修改产品文档 (ID: 1) 的价格,并将其设置为缺货

http
POST /products/_update/1
{
"doc": {
"price": 1100.00,
"in_stock": false
}
}

响应示例:

json
{
"_index": "products",
"_id": "1",
"_version": 3, // 版本号再次增加
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}

这种方式只会修改 doc 字段下的内容,而不会影响文档的其他字段。

6. 删除文档 (Delete Document)

通过文档的 ID 可以删除文档。

请求格式:

http
DELETE /<index_name>/_doc/<document_id>

示例:删除产品文档 (ID: 1)

http
DELETE /products/_doc/1

响应示例:

json
{
"_index": "products",
"_id": "1",
"_version": 4, // 删除操作也会增加版本号
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1
}

再次尝试获取该文档,会返回 found: false

7. 删除索引 (Delete Index)

删除整个索引会删除该索引下的所有文档和 Mapping 设置。

请求格式:

http
DELETE /<index_name>

示例:删除 products 索引

http
DELETE /products

响应示例:

json
{
"acknowledged": true // 表示请求已被集群确认
}

再次查看所有索引 (GET /_cat/indices?v),products 索引将不再列表中。

第四章:基本搜索查询 (Search)

Elasticsearch 最强大的功能在于其灵活且高性能的搜索能力。搜索通过 _search endpoint 进行,请求体中使用 Elasticsearch 特有的 Query DSL (Domain Specific Language) 来定义查询条件。Query DSL 是一个基于 JSON 的语言。

1. 查询所有文档

最简单的搜索请求是查询一个索引中的所有文档。

请求格式:

http
GET /<index_name>/_search

示例:查询 orders 索引中的所有文档

假设我们之前创建了一个 orders 索引并添加了一些文档。

http
GET /orders/_search

响应示例 (部分):

json
{
"took": 3, // 查询花费的毫秒数
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": { // 搜索结果的核心部分
"total": { // 总命中数
"value": 10000,
"relation": "gte" // 表示实际命中数可能大于等于 10000 (默认限制)
},
"max_score": 1.0, // 最高相关度分数
"hits": [ // 具体命中的文档列表
{
"_index": "orders",
"_id": "AbCdefGhIjKlMnOqrSTu",
"_version": 1,
"_score": 1.0, // 相关度分数
"_source": { // 原始文档内容
"order_id": "ORD12345",
"customer_name": "Alice",
"amount": 250.75,
"order_date": "2023-10-27T10:30:00Z"
}
},
// ... 更多文档
]
}
}

注意 hits 部分,total 表示匹配到的文档总数,hits 数组包含了返回的文档详情。默认情况下,返回前 10 条文档。

2. 基本查询参数

可以在 _search 请求体中添加参数来控制查询行为,最常见的是 query 参数。

请求格式 (带 query):

http
GET /<index_name>/_search
{
"query": {
// Query DSL 定义查询条件
}
}

3. 常用查询类型

Query DSL 提供了各种查询类型来满足不同的搜索需求。

a. 匹配查询 (Match Query)

用于执行全文搜索。它会分析查询文本,然后匹配文档中被分析的字段。

请求格式:

http
GET /<index_name>/_search
{
"query": {
"match": {
"<field_name>": "<query_text>"
}
}
}

示例:在 orders 索引中搜索 customer_name 包含 “Alice” 的订单

http
GET /orders/_search
{
"query": {
"match": {
"customer_name": "Alice"
}
}
}

如果 customer_name 字段是 text 类型,match 查询会对其进行分词处理。

示例:在 products 索引中搜索 description 包含 “Powerful laptop” 的产品

如果之前创建了带有 description 字段的 products 索引。

http
GET /products/_search
{
"query": {
"match": {
"description": "Powerful laptop"
}
}
}

b. 词条查询 (Term Query)

用于精确匹配字段中的一个未分析的词条 (term)。通常用于 keyword 字段或者不进行分词处理的字段(如数字、日期、布尔值)。它不会对查询文本进行分词处理。

重要提示: 对于 text 字段,Elasticsearch 会创建一个子字段(通常命名为 .keyword),它是该字段的未分析版本。使用 term 查询 text 字段时,通常应该查询其 .keyword 子字段。

请求格式:

http
GET /<index_name>/_search
{
"query": {
"term": {
"<field_name>": "<exact_value>"
}
}
}

示例:在 products 索引中搜索 brand 字段精确等于 “Dell” 的产品

假设 brand 字段是 keyword 类型。

http
GET /products/_search
{
"query": {
"term": {
"brand": "Dell"
}
}
}

示例:在 products 索引中搜索 in_stock 字段等于 true 的产品

假设 in_stock 字段是 boolean 类型。

http
GET /products/_search
{
"query": {
"term": {
"in_stock": true
}
}
}

区别 match vs term match 用于全文搜索(对查询和文档字段都分词后匹配),term 用于精确匹配(不对查询分词,直接匹配文档中未分析的词条)。这是初学者常遇到的一个难点,理解字段的 Mapping(特别是 textkeyword)以及查询类型的适用场景非常重要。

c. 范围查询 (Range Query)

用于查找字段值在指定范围内的文档。常用于数字和日期字段。

请求格式:

http
GET /<index_name>/_search
{
"query": {
"range": {
"<field_name>": {
"gte": <min_value>, // 大于等于
"gt": <min_value>, // 大于
"lte": <max_value>, // 小于等于
"lt": <max_value> // 小于
}
}
}
}

示例:在 products 索引中搜索价格 (price) 在 1000 到 1500 之间的产品 (包含边界)

http
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 1000,
"lte": 1500
}
}
}
}

示例:在 orders 索引中搜索 2023 年 10 月份的订单

假设 order_datedate 类型。

http
GET /orders/_search
{
"query": {
"range": {
"order_date": {
"gte": "2023-10-01T00:00:00Z",
"lt": "2023-11-01T00:00:00Z"
}
}
}
}

4. 组合查询 (Boolean Query)

布尔查询 (Boolean Query) 允许你使用布尔逻辑 (AND, OR, NOT) 组合多个查询子句。这是最常用和强大的查询类型之一。

布尔查询包含以下子句:

  • must: 文档必须匹配此子句,相当于 AND。
  • filter: 文档必须匹配此子句,但子句会以非计分模式 (non-scoring mode) 执行。用于过滤结果而不影响相关度分数。常用于结构化搜索(如范围、Term、ID 查询)。也相当于 AND,但性能通常优于 must 用于过滤场景。
  • should: 文档应该匹配此子句。如果文档匹配 mustfilter 子句,则 should 子句的匹配会提高文档的相关度分数。如果文档不匹配任何 mustfilter 子句,那么至少需要匹配一个 should 子句(默认情况下)才能被返回,相当于 OR。
  • must_not: 文档不能匹配此子句,相当于 NOT。以非计分模式执行。

请求格式:

http
GET /<index_name>/_search
{
"query": {
"bool": {
"must": [
// 匹配子句列表 (AND)
],
"filter": [
// 过滤子句列表 (AND, 非计分)
],
"should": [
// 推荐子句列表 (OR, 影响分数)
],
"must_not": [
// 排除子句列表 (NOT, 非计分)
]
}
}
}

示例:在 products 索引中搜索品牌是 “Dell” 或 “HP”,价格在 1000 到 2000 之间,并且描述中包含 “laptop” 但不包含 “gaming” 的产品

http
GET /products/_search
{
"query": {
"bool": {
"should": [
{ "term": { "brand.keyword": "Dell" } },
{ "term": { "brand.keyword": "HP" } }
],
"minimum_should_match": 1, // 至少匹配一个 should 子句
"filter": [
{
"range": {
"price": {
"gte": 1000,
"lte": 2000
}
}
}
],
"must": [
{ "match": { "description": "laptop" } }
],
"must_not": [
{ "match": { "description": "gaming" } }
]
}
}
}

这个示例结合了多种查询类型和布尔逻辑,展示了 Query DSL 的灵活性。注意 brand.keyword 的使用,假设 brand 字段的 Mapping 中有一个 keyword 子字段。minimum_should_match 参数指定 should 子句中至少需要匹配多少个子句才返回文档。

5. 分页与排序

  • 分页: 使用 fromsize 参数控制返回结果的起始位置和数量。
    http
    GET /<index_name>/_search
    {
    "query": { ... },
    "from": 10, // 跳过前 10 条
    "size": 20 // 返回 20 条
    }
  • 排序: 使用 sort 参数指定排序字段和排序方式 (asc 升序, desc 降序)。
    http
    GET /<index_name>/_search
    {
    "query": { ... },
    "sort": [
    { "price": "asc" }, // 按价格升序
    { "order_date": "desc" } // 再按日期降序
    ]
    }

    注意:对 text 字段进行排序通常需要在其 keyword 子字段上进行。

6. 指定返回字段 (_source)

默认情况下,搜索结果会返回整个原始文档 (_source)。你可以通过 _source 参数来指定只返回文档中的部分字段,这在文档很大时可以节省带宽和处理时间。

http
GET /<index_name>/_search
{
"query": { ... },
"_source": ["field1", "field3"] // 只返回 field1 和 field3
}

或者排除某些字段:

http
GET /<index_name>/_search
{
"query": { ... },
"_source": {
"excludes": ["sensitive_field"] // 排除 sensitive_field
}
}

第五章:更进一步:Mapping 和 Aggregations (简介)

1. 理解并控制 Mapping

前面提到,Mapping 定义了字段的数据类型和索引方式。手动创建和管理 Mapping 非常重要,特别是为了精确控制文本分析和字段类型。

示例:手动创建索引并定义 Mapping

创建一个名为 blogs 的索引,并定义字段类型:

http
PUT /blogs
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"title": {
"type": "text" // 用于全文搜索
},
"author": {
"type": "keyword" // 用于精确匹配、排序、聚合
},
"publish_date": {
"type": "date" // 日期类型
},
"tags": {
"type": "keyword" // 标签列表,每个标签都可精确匹配
},
"views": {
"type": "long" // 数字类型
},
"content": {
"type": "text",
"analyzer": "standard" // 指定标准分词器 (默认)
}
}
}
}

获取现有索引的 Mapping:

http
GET /<index_name>/_mapping

了解并设置正确的 Mapping 是构建高效搜索和分析的基础。

2. 聚合 (Aggregations)

聚合是 Elasticsearch 的另一个强大功能,它允许你对搜索结果进行分组、计算统计信息(如总和、平均值、最大/最小值)、创建直方图等。这使得 Elasticsearch 不仅是搜索引擎,也是一个强大的分析引擎。

聚合与查询是分开的,可以在同一个请求中同时执行。

示例:按品牌统计产品数量

http
GET /products/_search
{
"size": 0, // 不返回搜索结果,只返回聚合结果
"aggs": { // aggregations 的缩写
"products_by_brand": { // 聚合名称
"terms": { // 按词条(这里是品牌)分组
"field": "brand.keyword" // 聚合字段 (通常使用 keyword 字段)
}
}
}
}

响应示例 (部分):

json
{
...
"hits": { ... }, // size: 0 时 hits 数组是空的
"aggregations": {
"products_by_brand": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [ // 分组结果
{
"key": "Dell", // 品牌名称
"doc_count": 500 // 该品牌的文档数量
},
{
"key": "HP",
"doc_count": 400
},
// ... 更多品牌
]
}
}
}

聚合是 Elasticsearch 实现数据分析和可视化的关键。Kibana 中的 Visualize 功能就是基于 Elasticsearch 的聚合 API 实现的。

第六章:超越入门

本教程覆盖了 Elasticsearch 的核心概念、基本安装和常用的 CRUD (创建、读取、更新、删除) 及搜索操作。但这仅仅是冰山一角。要更深入地使用 Elasticsearch,还需要学习:

  • 更高级的查询: 短语查询 (match_phrase), 前缀查询 (prefix), 通配符查询 (wildcard), 正则表达式查询 (regexp), fuzzy 查询 (fuzzy), More Like This 查询等。
  • 全文搜索的奥秘: 深入理解分析器 (Analyzer),包括字符过滤器 (Character Filters), 分词器 (Tokenizer), 词条过滤器 (Token Filters)。如何创建自定义分析器。
  • 相关度评分: 了解 TF/IDF 或 BM25 等评分算法,以及如何通过提升 (boosting) 或其他方法影响文档的相关度。
  • 高级聚合: 管道聚合 (Pipeline Aggregations), 矩阵聚合 (Matrix Aggregations) 等。
  • 集群管理: 多节点集群的搭建和管理,主节点选举,分片分配策略。
  • 性能优化: 索引设计,查询优化,内存和磁盘调优。
  • 数据摄入: 使用 Logstash, Beats 或 Ingest Node 管道导入和处理数据。
  • 安全性: 用户认证、授权、加密等。
  • 监控与报警: 使用 Elastic Stack 的 X-Pack 功能或第三方工具进行监控。
  • 跨集群搜索 (Cross-Cluster Search) 和跨集群复制 (Cross-Cluster Replication)。

学习资源:

总结

恭喜你完成了这篇 Elasticsearch 快速入门教程!我们一起了解了 Elasticsearch 的核心概念,成功搭建了本地环境并进行了基础的数据操作和搜索。

你现在应该对 Elasticsearch 有了初步的认识,并且具备了继续深入学习的基础。记住,实践是最好的学习方法,尝试使用 Kibana Dev Tools 或你喜欢的编程语言客户端(Java, Python, Go, Node.js 等都提供了官方客户端库)来操作你的 Elasticsearch 实例,索引自己的数据,尝试不同的查询和聚合。

Elasticsearch 是一个功能强大且生态系统完善的平台,掌握它将极大地提升你在处理海量数据时的能力。祝你在后续的 Elasticsearch 学习和使用中取得成功!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部