work hard work smart

专注于AI+Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Python 中使用 Elasticsearch 的完整指南

Posted on 2026-07-05 14:22  work hard work smart  阅读(1)  评论(0)    收藏  举报

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 的组合都能为您提供强大的支持。