A complete FastAPI application demonstrating Elasticsearch integration for blog post search functionality. Perfect for learning how to implement full-text search in your FastAPI applications.
- π FastAPI - Modern, fast web framework for building APIs
- π Elasticsearch - Powerful full-text search engine
- π Blog Post CRUD - Create, Read, Update, Delete operations
- π Advanced Search - Full-text search with filters, fuzzy matching, and relevance scoring
- π³ Docker Compose - Easy setup with Elasticsearch and Kibana
- π Kibana - Visualize and manage your Elasticsearch data
- π― Type Safety - Pydantic models for request/response validation
- π Auto Documentation - Interactive API docs with Swagger UI
fastapi-elasticsearch-blog/
βββ app/
β βββ __init__.py
β βββ main.py # FastAPI application entry point
β βββ config.py # Configuration settings
β βββ schemas.py # Pydantic models
β βββ elasticsearch_client.py # Elasticsearch client setup
β βββ routers/
β βββ __init__.py
β βββ blog_router.py # Blog post endpoints
βββ scripts/
β βββ (tutorial scripts) # Step-by-step tutorial scripts
βββ docker-compose.yml # Docker services configuration
βββ pyproject.toml # Project configuration and dependencies (uv)
βββ seed_data.py # Script to populate sample data
βββ test_search.py # Test search functionality
βββ README.md
- Python 3.11+
- Docker and Docker Compose
- uv - Modern Python package and project manager (required)
cd fastapi-elasticsearch-blogdocker-compose up -dWait a minute for Elasticsearch to fully start. You can check if it's ready:
curl http://localhost:9200# Install uv if you haven't already
pip install uv
# Sync dependencies (creates virtual environment automatically)
uv syncThe application uses default settings that work out of the box. If you need to customize:
# Create .env file (optional)
ELASTICSEARCH_HOST=http://localhost:9200
ELASTICSEARCH_INDEX=blog_posts
DATABASE_URL=postgresql+asyncpg://blog_user:blog_password@localhost:5432/blog_dbuv run python seed_data.pyThis will create 15 sample blog posts in Elasticsearch.
uv run uvicorn app.main:app --reloadThe API will be available at:
- API: http://localhost:8000
- Interactive Docs: http://localhost:8000/docs
- Kibana: http://localhost:5601
- POST
/api/v1/posts- Create a new blog post - GET
/api/v1/posts/{post_id}- Get a single post by ID - PUT
/api/v1/posts/{post_id}- Update a post - DELETE
/api/v1/posts/{post_id}- Delete a post - GET
/api/v1/posts- List all posts (with pagination)
- POST
/api/v1/search- Search blog posts
- GET
/health- Check API and Elasticsearch health - GET
/- API information
curl -X POST "http://localhost:8000/api/v1/posts" \
-H "Content-Type: application/json" \
-d '{
"title": "My First Blog Post",
"content": "This is the content of my blog post about Elasticsearch and FastAPI.",
"author": "John Doe",
"tags": ["elasticsearch", "fastapi", "python"],
"status": "published"
}'curl -X POST "http://localhost:8000/api/v1/search" \
-H "Content-Type: application/json" \
-d '{
"query": "elasticsearch tutorial",
"from": 0,
"size": 10
}'curl -X POST "http://localhost:8000/api/v1/search" \
-H "Content-Type: application/json" \
-d '{
"query": "python",
"tags": ["fastapi", "tutorial"],
"author": "John Doe",
"status": "published",
"from": 0,
"size": 10
}'curl "http://localhost:8000/api/v1/posts/{post_id}"curl "http://localhost:8000/api/v1/posts?from_=0&size=10&status_filter=published"- Multi-field search across title and content
- Field boosting (title matches score higher)
- Fuzzy matching for typo tolerance
- Filter by tags (exact match)
- Filter by author (keyword match)
- Filter by status (term match)
- Best fields matching
- Score-based sorting combined with date sorting
- Custom index mappings
- Text and keyword field types
- Date and integer fields
- View count tracking
- Document update with scripts
Run the test search script to see search functionality in action:
uv run python test_search.pyThis will test various search queries and show the results with highlighting.
Access Kibana at http://localhost:5601 to:
- View your blog posts index
- Run custom Elasticsearch queries
- Visualize search analytics
- Manage index settings
Navigate to: Menu β Dev Tools β Console to run Elasticsearch queries directly.
Example query in Kibana Console:
GET /blog_posts/_search
{
"query": {
"match": {
"content": "elasticsearch"
}
}
}The index uses custom mappings to optimize search:
{
"title": {
"type": "text", # Full-text search
"fields": {
"keyword": { # Exact match filtering
"type": "keyword"
}
}
}
}Search across multiple fields with different weights:
{
"multi_match": {
"query": "search term",
"fields": ["title^2", "content"], # Title is 2x more important
"fuzziness": "AUTO" # Handle typos
}
}Combine multiple query conditions:
{
"bool": {
"must": [/* queries that must match */],
"filter": [/* queries that filter results */]
}
}curl -X DELETE "http://localhost:9200/blog_posts"
uv run python seed_data.pycurl "http://localhost:9200/blog_posts/_search?pretty"curl "http://localhost:9200/blog_posts/_mapping?pretty"curl "http://localhost:9200/_cluster/health?pretty"- Make sure Docker is running
- Check if ports 9200 and 9300 are available
- Increase Docker memory allocation (Settings β Resources)
- Wait a minute after starting docker-compose
- Check Elasticsearch logs:
docker-compose logs elasticsearch
- Make sure you installed dependencies:
uv sync - uv automatically creates and manages virtual environments
- Always use
uv runto execute scripts in the project environment
- Run
python seed_data.pyto populate data - Check if index exists:
curl http://localhost:9200/_cat/indices
This project uses uv for fast, reliable Python package management:
# Add a new package
uv add package-name
# Remove a package
uv remove package-name
# Update dependencies
uv sync
# Run any Python script in the project environment
uv run python script.pyMIT License - Feel free to use this project for learning and development.
This is a tutorial project, but suggestions and improvements are welcome!
Happy Searching! π