1.2 Elasticsearch 核心概念 1.2 Elasticsearch 核心概念 Elasticsearch 是一个分布式、RESTful 风格的搜索和分析引擎,它基于 Apache Lucene 构建,提供了近乎实时的搜索能力。理解其核心概念是掌握 Elasticsearch 的关键。 1.2.1 索引 (Index) 概念: 在 Elasticsearch 中,索引类似于关系型数据库中的数据库。 它是一个存储相关文档的集合。 你可以将索引视为一个组织数据的逻辑容器。 索引通过名称来标识 (例如, , )。 一个 Elasticsearch 集群可以包含多个索引。 代码实践 (使用 Elasticsearch Python 客户端): 详解: 用于创建一个新的索引。
Elasticsearch 是一个分布式、RESTful 风格的搜索和分析引擎,它基于 Apache Lucene 构建,提供了近乎实时的搜索能力。理解其核心概念是掌握 Elasticsearch 的关键。
概念:
在 Elasticsearch 中,索引类似于关系型数据库中的数据库。
它是一个存储相关文档的集合。
你可以将索引视为一个组织数据的逻辑容器。
索引通过名称来标识 (例如,"products", "logs")。
一个 Elasticsearch 集群可以包含多个索引。
代码实践 (使用 Elasticsearch Python 客户端):
from elasticsearch import Elasticsearch # 连接到 Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # 创建一个名为 "my_index" 的索引 index_name = "my_index" if not es.indices.exists(index=index_name): es.indices.create(index=index_name) print(f"索引 '{index_name}' 创建成功") else: print(f"索引 '{index_name}' 已经存在") # 删除索引 #es.indices.delete(index=index_name) #print(f"索引 '{index_name}' 删除成功")
详解:
es.indices.create(index=index_name) 用于创建一个新的索引。
es.indices.exists(index=index_name) 用于检查索引是否存在。
索引创建时,可以指定 settings (例如,分片数量、副本数量) 和 mappings (定义字段类型)。
索引删除后,其中的数据将永久丢失,请谨慎操作。
概念:
文档是 Elasticsearch 中存储的基本单元,类似于关系型数据库中的行。
文档是一个 JSON 对象,包含多个字段 (key-value 对)。
每个文档都属于一个索引。
文档通过唯一的 _id 字段来标识。
代码实践:
from elasticsearch import Elasticsearch # 连接到 Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # 准备文档数据 document = { "title": "Elasticsearch 权威指南", "author": "Clinton Gormley, Zachary Tong", "publish_date": "2015-08-05", "tags": ["elasticsearch", "search", "distributed"] } # 索引文档 index_name = "my_index" document_id = 1 response = es.index(index=index_name, id=document_id, document=document) print(response) # 获取文档 get_response = es.get(index=index_name, id=document_id) print(get_response['_source'])
详解:
es.index() 用于索引一个文档到指定的索引。
index 参数指定索引名称,id 参数指定文档 ID,document 参数指定文档数据。
如果指定的 ID 已经存在,则会更新该文档。
es.get() 用于根据 ID 获取文档。
_source 字段包含文档的原始 JSON 数据。
概念:
字段是文档中的一个 key-value 对。
每个字段都有一个名称 (key) 和一个值 (value)。
字段的值可以是各种数据类型,例如 text, keyword, date, integer, boolean 等。
字段的类型在 mapping 中定义。
代码实践 (Mapping):
from elasticsearch import Elasticsearch # 连接到 Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # 定义 Mapping mapping = { "properties": { "title": {"type": "text"}, "author": {"type": "keyword"}, "publish_date": {"type": "date", "format": "yyyy-MM-dd"}, "tags": {"type": "keyword"} } } # 创建索引并指定 Mapping index_name = "my_index" if not es.indices.exists(index=index_name): es.indices.create(index=index_name, mappings=mapping) print(f"索引 '{index_name}' 创建成功,并指定了 Mapping") else: print(f"索引 '{index_name}' 已经存在")
详解:
Mapping 定义了索引中每个字段的类型和其他属性。
properties 字段包含字段名称和类型的映射。
type 指定字段的数据类型。
format 指定日期字段的格式。
选择合适的字段类型对于搜索和分析至关重要。 例如, text 类型适用于全文搜索,而 keyword 类型适用于精确匹配。
注意:在 Elasticsearch 之后,Type 的概念已经被移除。 一个索引现在只允许有一个默认的 Type,通常命名为 _doc。 以下内容仅为历史参考。
概念:
在 Elasticsearch 之前,一个索引可以包含多个类型。
类型用于在索引中对文档进行逻辑分组。
类型类似于关系型数据库中的表。
每个文档都属于一个类型。
为什么移除 Type?
Elasticsearch 的设计者意识到,在同一个索引中,不同类型的字段应该具有相同的类型定义。 如果不同类型的字段名称相同,但类型定义不同,会导致混乱和性能问题。
移除 Type 可以简化 Elasticsearch 的数据模型,并提高性能。
现在应该怎么做?
如果需要对文档进行逻辑分组,应该使用不同的索引。
可以使用 _type 字段来模拟 Type 的行为 (但不推荐)。
概念:
Mapping 定义了索引中每个字段的类型和其他属性。
它类似于关系型数据库中的 schema。
Mapping 决定了如何索引和搜索文档中的数据。
Mapping 可以是动态的 (自动创建) 或静态的 (手动定义)。
代码实践 (动态 Mapping):
from elasticsearch import Elasticsearch # 连接到 Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # 索引文档 (没有预先定义 Mapping) index_name = "my_index" document = {"product_name": "Awesome T-Shirt", "price": 25.99} response = es.index(index=index_name, document=document) print(response) # 获取 Mapping mapping = es.indices.get_mapping(index=index_name) print(mapping)
详解:
如果没有预先定义 Mapping,Elasticsearch 会根据文档的数据类型自动创建 Mapping。
es.indices.get_mapping() 用于获取索引的 Mapping。
动态 Mapping 方便快速开始,但建议为生产环境手动定义 Mapping,以确保数据类型和搜索行为符合预期。
概念:
分片是 Elasticsearch 中数据的基本单元。
一个索引可以被分成多个分片。
每个分片都是一个独立的 Lucene 索引。
分片允许 Elasticsearch 水平扩展,处理大量数据。
有两种类型的分片:主分片 (Primary Shard) 和副本分片 (Replica Shard)。
主分片:
主分片用于存储原始数据。
主分片的数量在索引创建时确定,并且不能更改 (除非 reindex)。
主分片决定了索引可以存储的最大数据量。
副本分片:
副本分片是主分片的副本。
副本分片提供数据冗余,提高可用性。
副本分片可以用于读取请求,提高搜索性能。
副本分片的数量可以动态调整。
图示:
代码实践 (指定分片数量):
from elasticsearch import Elasticsearch # 连接到 Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # 创建索引并指定分片数量 index_name = "my_index" settings = { "number_of_shards": 3, # 主分片数量 "number_of_replicas": 1 # 副本分片数量 } if not es.indices.exists(index=index_name): es.indices.create(index=index_name, settings=settings) print(f"索引 '{index_name}' 创建成功,并指定了分片数量") else: print(f"索引 '{index_name}' 已经存在")
详解:
number_of_shards 设置主分片数量。
number_of_replicas 设置副本分片数量。
合理设置分片数量对于性能和可扩展性至关重要。
主分片数量取决于数据量和集群规模。
副本分片数量取决于可用性需求。
概念:
集群是由一个或多个 Elasticsearch 节点组成的集合。
集群提供数据存储、搜索和分析能力。
集群中的节点协同工作,实现负载均衡和故障转移。
一个 Elasticsearch 实例就是一个节点。
图示:
详解:
每个节点都运行 Elasticsearch 实例。
节点可以扮演不同的角色,例如 master 节点、data 节点、ingest 节点等。
Master 节点负责管理集群状态。
Data 节点负责存储数据和执行搜索。
Ingest 节点负责数据预处理。
集群的健康状态可以通过 API 获取。
代码实践 (查看集群健康状态):
from elasticsearch import Elasticsearch # 连接到 Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # 获取集群健康状态 health = es.cluster.health() print(health)
总结:
理解 Elasticsearch 的核心概念是使用 Elasticsearch 的基础。 通过本文的讲解和代码实践,你应该对索引、文档、字段、映射、分片和集群有了更深入的了解。 在实际应用中,需要根据具体场景选择合适的配置,以获得最佳的性能和可用性。