最近在帮一个电商客户搭建商品搜索服务时,我再次验证了FastAPI和Elasticsearch这对黄金组合的高效性。这个技术栈特别适合需要快速构建高性能搜索服务的场景,比如电商平台、内容管理系统或者日志分析工具。
FastAPI作为Python生态中性能顶尖的Web框架,其异步特性与Elasticsearch的分布式搜索能力简直是天作之合。我在实际项目中测得,一个基础的商品搜索接口,在本地开发环境下QPS能轻松突破800,响应时间稳定在50ms以内。
我习惯使用Python 3.8+版本进行开发,这个版本在异步IO性能和支持库兼容性方面表现最稳定。以下是必备组件清单:
bash复制# 创建虚拟环境
python -m venv es_env
source es_env/bin/activate # Linux/Mac
es_env\Scripts\activate # Windows
# 安装核心依赖
pip install fastapi uvicorn elasticsearch python-dotenv
注意:Elasticsearch的Python客户端有新旧两个版本,这里使用的是官方推荐的elasticsearch包(版本8.x),而不是老旧的elasticsearch-py
我推荐使用Docker部署Elasticsearch,省去手动配置的麻烦:
bash复制docker pull docker.elastic.co/elasticsearch/elasticsearch:8.5.3
docker network create elastic
docker run --name es01 --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -t docker.elastic.co/elasticsearch/elasticsearch:8.5.3
部署完成后,可以通过curl测试服务是否正常:
bash复制curl -X GET "localhost:9200/?pretty"
如果看到包含"you-know, for search"的JSON响应,说明Elasticsearch已成功启动。
我的典型项目目录如下:
code复制/fastapi-es-project
├── .env # 环境变量
├── app
│ ├── __init__.py
│ ├── main.py # FastAPI主入口
│ ├── models.py # 数据模型
│ ├── schemas.py # Pydantic模型
│ └── services # 业务逻辑
│ └── es_service.py
└── requirements.txt
在es_service.py中,我通常会封装一个Elasticsearch操作类:
python复制from elasticsearch import AsyncElasticsearch
import os
from dotenv import load_dotenv
load_dotenv()
class ElasticsearchService:
def __init__(self):
self.client = AsyncElasticsearch(
hosts=[os.getenv("ES_HOST", "http://localhost:9200")],
http_auth=(
os.getenv("ES_USER", "elastic"),
os.getenv("ES_PASSWORD", "")
),
verify_certs=False # 开发环境可关闭证书验证
)
async def search(self, index: str, query: dict):
return await self.client.search(index=index, body=query)
async def close(self):
await self.client.close()
在main.py中创建核心路由:
python复制from fastapi import FastAPI, Depends
from app.schemas import SearchRequest
from app.services.es_service import ElasticsearchService
app = FastAPI()
@app.on_event("shutdown")
async def shutdown_event():
await app.state.es.close()
@app.post("/search")
async def search_products(request: SearchRequest):
es = ElasticsearchService()
app.state.es = es # 保存实例用于关闭
query = {
"query": {
"multi_match": {
"query": request.keyword,
"fields": ["name^3", "description"]
}
},
"size": request.size
}
results = await es.search("products", query)
return {
"data": results["hits"]["hits"],
"total": results["hits"]["total"]["value"]
}
在生产环境中,一定要配置连接池:
python复制self.client = AsyncElasticsearch(
hosts=[ES_HOST],
maxsize=20, # 连接池大小
timeout=30, # 超时时间(秒)
retry_on_timeout=True,
max_retries=3
)
根据我的经验,这些查询优化技巧很实用:
python复制# 优化后的查询示例
{
"query": {
"bool": {
"must": [
{"match": {"name": {"query": "手机", "boost": 3}}}
],
"filter": [
{"range": {"price": {"gte": 1000, "lte": 5000}}}
]
}
},
"_source": ["id", "name", "price"] # 只返回必要字段
}
如果遇到连接超时,可以按这个流程排查:
bash复制curl -X GET "localhost:9200/_cluster/health?pretty"
Elasticsearch 8.x默认开启安全认证,如果遇到认证问题:
bash复制docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
这套基础架构可以进一步扩展:
我在实际项目中发现,配合Kibana进行搜索词分析能显著提升搜索质量。通过分析用户高频搜索词和零结果查询,可以持续优化搜索算法和商品标签体系。