Elasticsearch使用指南(Python)
Elasticsearch搜索引擎使用python sdk的指南!
前置准备
确保已安装 Elasticsearch 服务器并运行,Python 环境中安装了 elasticsearch 库。
pip install elasticsearch
1. 连接 Elasticsearch
首先,导入 elasticsearch 库并连接到运行的 Elasticsearch 实例。
#如果需要使用异步 async,需要使用AsyncElasticsearch, 在使用的时候 await es.xxx
from elasticsearch import Elasticsearch
# 创建连接对象
es = Elasticsearch(hosts=["http://localhost:9200"])
2. 设置映射(Mapping)
映射是指为 Elasticsearch 索引中的文档字段定义数据类型。映射设置得当,可以提高索引和搜索的性能。例如,以下代码创建一个名为 my_index 的索引,并为其字段定义了数据类型。
# 定义映射
mapping = {
"mappings": {
"properties": {
"title": {
"type": "text"
},
"description": {
"type": "text"
},
"publish_date": {
"type": "date"
},
"author": {
"type": "keyword"
},
"vector_field": {
"type": "dense_vector",
"dims": 128 # 假设向量维度是128
}
}
}
}
# 创建索引
if not es.indices.exists(index="my_index"):
es.indices.create(index="my_index", body=mapping)
注意事项
text类型用于全文搜索;keyword类型适合短文本且不需要分词;dense_vector是向量类型,适用于基于向量的相似度计算。
3. 重置映射
若需重置索引的映射(Mapping),通常需要删除并重新创建索引。Elasticsearch 不支持在已有索引上直接更改映射,因此我们可以按以下步骤重置:
# 删除索引
es.indices.delete(index="my_index", ignore=[400, 404])
# 重新创建索引
es.indices.create(index="my_index", body=mappi但是可以添加新的
4. 插入文档
接下来,我们在 my_index 索引中添加一些示例文档。
# 插入单个文档
doc1 = {
"title": "Python教程",
"description": "详细介绍Python编程语言的教程",
"publish_date": "2023-11-01",
"author": "张三",
"vector_field": [0.1] * 128 # 示例向量
}
# 使用文档ID插入文档
es.index(index="my_index", id=1, document=doc1)
批量插入
可以使用 bulk API 一次插入多条记录,提高插入效率。
from elasticsearch.helpers import bulk
# 批量插入文档
actions = [
{
"_index": "my_index",
"_id": 2,
"_source": {
"title": "机器学习基础",
"description": "适合初学者的机器学习教程",
"publish_date": "2024-01-10",
"author": "李四",
"vector_field": [0.2] * 128
}
},
# 可以添加更多文档
]
bulk(es, actions)
此处添加的向量可以使用huggingface的sentence_transformer,后面会写更详细的教程。
5. 更新已有文档
Elasticsearch 提供了 update 方法来部分更新文档内容。以下是更新文档ID为 1 的示例。
# 部分更新文档
update_doc = {
"doc": {
"description": "更新后的Python教程描述"
}
}
es.update(index="my_index", id=1, body=update_doc)
6. 基于向量和文本匹配的搜索
基本文本搜索
首先,我们可以使用 match 查询文本字段的全文搜索。例如,搜索包含“教程”的 title 文档。
# 简单文本搜索
query = {
"query": {
"match": {
"title": "教程"
}
}
}
result = es.search(index="my_index", body=query)
for hit in result["hits"]["hits"]:
print(hit["_source"])
基于向量的搜索
若需进行向量相似度搜索,Elasticsearch 支持 dense_vector 和 cosineSimilarity。以下示例展示如何基于向量字段 vector_field 进行相似度搜索:
# 示例向量查询
query_vector = [0.1] * 128 # 这是要匹配的查询向量
query = {
"query": {
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "cosineSimilarity(params.query_vector, 'vector_field') + 1.0",
"params": {"query_vector": query_vector}
}
}
}
}
result = es.search(index="my_index", body=query)
for hit in result["hits"]["hits"]:
print(hit["_source"], "Score:", hit["_score"])
这里的 script_score 使用了 cosineSimilarity 函数计算向量相似度,通过 +1.0 避免相似度为负值。
基于向量和文本的复合搜索
可以结合 must 和 should 条件,将文本匹配和向量相似度结合:
# 复合查询
query = {
"query": {
"bool": {
"must": [
{"match": {"title": "教程"}}
],
"should": [
{
"script_score": {
"query": {"match_all": {}},
"script": {
"source": "cosineSimilarity(params.query_vector, 'vector_field') + 1.0",
"params": {"query_vector": query_vector}
}
}
}
]
}
}
}
result = es.search(index="my_index", body=query)
for hit in result["hits"]["hits"]:
print(hit["_source"], "Score:", hit["_score"])
在该查询中,must 部分匹配 title 包含“教程”的文档,而 should 部分计算向量相似度。这种方式可以实现基于文本和向量的多条件搜索。
7. 删除文档和索引
如果需要删除某个文档或整个索引,可以使用以下代码:
删除文档
# 删除文档
es.delete(index="my_index", id=1)
删除索引
# 删除整个索引
es.indices.delete(index="my_index", ignore=[400, 404])
总结
本文详细介绍了使用 Python 与 Elasticsearch 交互的基本操作,包括:
- 设置和重置映射(Mapping)
- 插入和批量插入文档
- 更新已有文档
- 基于向量和文本的复合搜索
- 删除文档和索引
这些操作基本覆盖了 Elasticsearch 的主要应用场景,能够帮助你熟练地构建、查询和管理索引。在实际应用中,可以根据业务需求调整查询条件与结构,以实现更高效的数据检索和处理。
注意事项
1. 映射设计
- 提前设计映射:在创建索引时尽可能设计好映射,因为一旦索引创建,映射的字段类型通常无法修改。如果必须修改映射,通常需要删除并重新创建索引。
- 合理使用字段类型:
text类型适合全文检索,keyword适合精确匹配,dense_vector则适合存储用于相似度计算的向量。选择合适的字段类型可以显著提升查询性能。 - 向量维度限制:
dense_vector字段的维度(dims参数)有硬件限制,建议控制在合理范围,通常不要超过 1024 维,以避免内存占用过高。
2. 批量插入
- 批量操作提升性能:使用
bulk方法批量插入数据,可以减少网络请求次数,显著提高性能。建议将批量操作的文档数控制在 5000 以内,以避免一次插入的数据过多导致内存溢出。 - 索引缓冲区设置:在大量插入数据前,可以临时增大
index.refresh_interval,并在插入完成后恢复默认值,从而减少刷新频率,提高插入速度。
3. 更新与删除文档
- 尽量少用频繁更新:Elasticsearch 的文档更新相当于删除旧文档并插入新文档,因此频繁更新可能导致索引碎片化,影响性能。建议减少更新操作,必要时定期重建索引。
- 延迟删除:对于一些非实时性强的删除操作,可以考虑批量删除或延迟删除,以减小对性能的影响。
4. 搜索性能
避免使用 match_all:如果索引包含大量数据,match_all查询会扫描整个索引,影响性能。可以结合过滤条件使用bool查询,缩小查询范围。- 脚本查询的性能影响:向量相似度计算中用到
script_score,这类脚本查询会消耗更多资源,影响查询性能。可以考虑将常用查询预先计算并缓存。 - 字段大小限制:
dense_vector字段的存储大小和数量会影响索引大小,建议只存储必要的字段并定期优化或重建索引。
5. 索引与数据管理
- 定期优化与重建索引:长时间使用后,索引可能会产生碎片,影响查询性能。可以定期对索引进行优化或重建,删除过期或无用的数据。
- 合理的分片设置:在创建索引时设置合理的分片数。对于小数据量,过多的分片会增加管理开销,而大数据量使用少量分片会导致单个分片负载过高。
6. 日志与监控
- 监控集群状态:定期检查 Elasticsearch 集群的健康状态,包括节点的 CPU、内存使用情况,以及各个索引的查询延迟等,以便及时发现性能瓶颈。
- 查看错误日志:在插入、查询或更新失败时,检查 Elasticsearch 的错误日志,了解可能的原因,并根据日志信息调整查询结构或索引设置。
7. 安全性
- 启用认证:在生产环境中,确保启用身份认证和权限控制,避免未经授权的访问。
- 避免暴露敏感信息:使用 Elasticsearch API 时,确保不将索引结构或敏感数据暴露给外部,必要时加密传输。
8. Python 与 Elasticsearch 兼容性
- 版本兼容:确保
elasticsearchPython 客户端库的版本与 Elasticsearch 服务器版本兼容,不同版本可能会导致 API 不一致。 - 连接池管理:对于高并发应用,建议使用连接池来管理与 Elasticsearch 的连接,避免频繁创建和销毁连接导致的性能开销。