Python 中使用 Elasticsearch 的完整指南
引言
Elasticsearch 是一个开源的分布式搜索和分析引擎,基于 Lucene 库构建,具有高性能、高可用和可扩展的特点。它被广泛用于日志分析、全文搜索、企业搜索和实时数据分析等场景。
Python 是一种功能强大且易于使用的编程语言,拥有丰富的库和工具生态系统。Elasticsearch 官方提供了 Python 客户端,使得在 Python 中与 Elasticsearch 进行交互变得非常简单。
本文将介绍如何在 Python 中使用 Elasticsearch,包括连接管理、索引操作、数据查询和最佳实践等内容。
1. 安装与配置
1.1 安装 Elasticsearch
首先,您需要安装 Elasticsearch。以下是在不同操作系统上的安装方法:
Windows:
# 下载 Elasticsearch 安装包(.zip 文件)
# 解压后运行 bin/elasticsearch.bat
Linux/Mac:
# 使用 Docker 安装(推荐)
docker pull elasticsearch:8.19.3
docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:8.19.3
1.2 安装 Python 客户端
使用 pip 安装 Elasticsearch Python 客户端:
pip install elasticsearch>=8,<9
2. 连接管理
2.1 基本连接
from elasticsearch import Elasticsearch
# 连接到本地 Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 检查连接是否成功
if es.ping():
print("成功连接到 Elasticsearch")
else:
print("无法连接到 Elasticsearch")
2.2 高级连接配置
from elasticsearch import Elasticsearch
# 连接到远程 Elasticsearch 集群
es = Elasticsearch(
["http://es-node1:9200", "http://es-node2:9200"],
http_auth=("username", "password"),
timeout=30,
max_retries=10,
retry_on_timeout=True
)
# 配置连接池
es = Elasticsearch(
"http://localhost:9200",
connection_pool_size=20,
maxsize=20,
timeout=60
)
2.3 异步连接
对于需要处理大量并发请求的应用,推荐使用异步客户端:
from elasticsearch import AsyncElasticsearch
import asyncio
async def main():
es = AsyncElasticsearch("http://localhost:9200")
if await es.ping():
print("成功连接到 Elasticsearch")
else:
print("无法连接到 Elasticsearch")
await es.close()
asyncio.run(main())
3. 索引操作
3.1 创建索引
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 简单创建索引
es.indices.create(index="books")
# 带配置的索引创建
es.indices.create(
index="books",
body={
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": {"type": "text"},
"author": {"type": "text"},
"release_date": {"type": "date"},
"page_count": {"type": "integer"}
}
}
}
)
3.2 删除索引
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
es.indices.delete(index="books")
3.3 索引管理
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 检查索引是否存在
if es.indices.exists(index="books"):
print("索引存在")
# 获取索引信息
index_info = es.indices.get(index="books")
print(index_info)
# 更新索引设置
es.indices.put_settings(
index="books",
body={"settings": {"number_of_replicas": 2}}
)
4. 文档操作
4.1 写入文档
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 插入文档(自动生成 ID)
es.index(
index="books",
document={
"name": "Snow Crash",
"author": "Neal Stephenson",
"release_date": "1992-06-01",
"page_count": 470
}
)
# 插入文档(指定 ID)
es.index(
index="books",
id=1,
document={
"name": "Snow Crash",
"author": "Neal Stephenson",
"release_date": "1992-06-01",
"page_count": 470
}
)
4.2 查询文档
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 根据 ID 查询
doc = es.get(index="books", id=1)
print(doc["_source"])
# 查询所有文档
resp = es.search(index="books")
print(resp["hits"]["hits"])
# 条件查询
resp = es.search(
index="books",
query={
"match": {"name": "Snow Crash"}
}
)
print(resp["hits"]["hits"])
# 范围查询
resp = es.search(
index="books",
query={
"range": {"page_count": {"gte": 400, "lte": 500}}
}
)
print(resp["hits"]["hits"])
4.3 更新文档
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 更新整个文档
es.index(
index="books",
id=1,
document={
"name": "Snow Crash Updated",
"author": "Neal Stephenson",
"release_date": "1992-06-01",
"page_count": 470
}
)
# 部分更新文档
es.update(
index="books",
id=1,
doc={
"page_count": 471
}
)
4.4 删除文档
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 删除单个文档
es.delete(index="books", id=1)
# 删除多个文档
es.delete_by_query(
index="books",
query={
"match": {"author": "Neal Stephenson"}
}
)
5. 搜索与查询
5.1 基本搜索
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 简单搜索
resp = es.search(
index="books",
query={
"match": {"name": "Snow"}
}
)
# 多字段搜索
resp = es.search(
index="books",
query={
"multi_match": {
"query": "Snow",
"fields": ["name", "author"]
}
}
)
5.2 复合查询
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 布尔查询
resp = es.search(
index="books",
query={
"bool": {
"must": [
{"match": {"name": "Snow"}},
{"range": {"page_count": {"gte": 400}}}
],
"must_not": [
{"match": {"author": "Unknown"}}
],
"should": [
{"match": {"author": "Neal"}}
]
}
}
)
5.3 聚合查询
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 统计文档数量
resp = es.search(
index="books",
aggs={
"total_books": {"value_count": {"field": "_id"}}
}
)
print(resp["aggregations"]["total_books"]["value"])
# 按作者分组统计
resp = es.search(
index="books",
aggs={
"books_by_author": {
"terms": {"field": "author.keyword"}
}
}
)
print(resp["aggregations"]["books_by_author"]["buckets"])
5.4 高亮搜索
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 高亮搜索结果
resp = es.search(
index="books",
query={"match": {"name": "Snow"}},
highlight={"fields": {"name": {}}}
)
for hit in resp["hits"]["hits"]:
print(hit["highlight"]["name"])
6. 高级功能
6.1 分页查询
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 分页查询
resp = es.search(
index="books",
query={"match_all": {}},
from_=0,
size=10
)
print(resp["hits"]["hits"])
6.2 排序查询
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 按字段排序
resp = es.search(
index="books",
query={"match_all": {}},
sort=[{"page_count": "asc"}]
)
print(resp["hits"]["hits"])
6.3 搜索建议
from elasticsearch import Elasticsearch
es = Elasticsearch("http://localhost:9200")
# 搜索建议
resp = es.search(
index="books",
query={"match": {"name": "Snw"}},
suggest={
"name_suggestion": {
"text": "Snw",
"term": {"field": "name"}
}
}
)
print(resp["suggest"]["name_suggestion"][0]["options"])
6.4 批量操作
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
es = Elasticsearch("http://localhost:9200")
# 准备数据
documents = [
{"name": "The Great Gatsby", "author": "F. Scott Fitzgerald", "release_date": "1925-04-10", "page_count": 180},
{"name": "To Kill a Mockingbird", "author": "Harper Lee", "release_date": "1960-07-11", "page_count": 281},
{"name": "1984", "author": "George Orwell", "release_date": "1949-06-08", "page_count": 328}
]
# 批量索引
def generate_docs():
for doc in documents:
yield {
"_index": "books",
"_source": doc
}
success, _ = bulk(es, generate_docs())
print(f"成功索引 {success} 个文档")
7. 最佳实践
7.1 连接管理
- 使用连接池管理连接
- 设置合理的超时时间
- 实现连接重试机制
- 避免频繁创建和关闭连接
7.2 查询优化
- 使用适当的查询类型
- 避免查询过宽的结果
- 合理使用过滤器和聚合
- 考虑使用索引别名
7.3 索引设计
- 为字段选择合适的数据类型
- 考虑使用多字段索引
- 定期优化索引
- 监控索引大小和性能
7.4 错误处理
from elasticsearch import Elasticsearch, TransportError
es = Elasticsearch("http://localhost:9200")
try:
# 执行操作
es.index(
index="books",
document={
"name": "Test Book",
"author": "Test Author",
"release_date": "2023-01-01",
"page_count": 100
}
)
except TransportError as e:
print(f"Elasticsearch 错误: {e}")
print(f"错误类型: {e.error}")
print(f"状态码: {e.status_code}")
except Exception as e:
print(f"其他错误: {e}")
8. 与其他库集成
8.1 与 Pandas 集成
from elasticsearch import Elasticsearch
import pandas as pd
es = Elasticsearch("http://localhost:9200")
# 从 Elasticsearch 读取数据到 DataFrame
resp = es.search(index="books", query={"match_all": {}})
df = pd.DataFrame([hit["_source"] for hit in resp["hits"]["hits"]])
print(df.head())
8.2 与 FastAPI 集成
from fastapi import FastAPI, Query
from elasticsearch import Elasticsearch
import uvicorn
app = FastAPI()
es = Elasticsearch("http://localhost:9200")
@app.get("/books/search")
def search_books(q: str = Query(None)):
if q:
resp = es.search(
index="books",
query={"match": {"name": q}}
)
return [hit["_source"] for hit in resp["hits"]["hits"]]
else:
resp = es.search(index="books", query={"match_all": {}})
return [hit["_source"] for hit in resp["hits"]["hits"]]
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
9. 总结
Elasticsearch 是一个功能强大的搜索引擎和分析工具,而 Python 提供了简单易用的客户端库,使得在 Python 中使用 Elasticsearch 变得非常方便。
本文介绍了 Elasticsearch 的基本操作,包括连接管理、索引操作、数据查询和高级功能。通过合理使用这些功能,您可以构建出强大的搜索和分析应用。
无论您是在开发日志分析系统、全文搜索引擎还是企业搜索平台,Elasticsearch 和 Python 的组合都能为您提供强大的支持。
作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!
浙公网安备 33010602011771号