Skip to content

Niklas-dev/fastapi-elasticsearch-blog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FastAPI Elasticsearch Blog Search

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.

Features

  • πŸš€ 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

Project Structure

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

Prerequisites

  • Python 3.11+
  • Docker and Docker Compose
  • uv - Modern Python package and project manager (required)

Quick Start

1. Clone or Download the Project

cd fastapi-elasticsearch-blog

2. Start Elasticsearch and Kibana

docker-compose up -d

Wait a minute for Elasticsearch to fully start. You can check if it's ready:

curl http://localhost:9200

3. Install Python Dependencies

# Install uv if you haven't already
pip install uv

# Sync dependencies (creates virtual environment automatically)
uv sync

4. (Optional) Create .env File

The 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_db

5. Seed Sample Data

uv run python seed_data.py

This will create 15 sample blog posts in Elasticsearch.

6. Run the Application

uv run uvicorn app.main:app --reload

The API will be available at:

API Endpoints

Blog Post Operations

  • 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)

Search

  • POST /api/v1/search - Search blog posts

Health Check

  • GET /health - Check API and Elasticsearch health
  • GET / - API information

Usage Examples

Create a Blog Post

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"
  }'

Search Blog Posts

curl -X POST "http://localhost:8000/api/v1/search" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "elasticsearch tutorial",
    "from": 0,
    "size": 10
  }'

Search with Filters

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
  }'

Get a Specific Post

curl "http://localhost:8000/api/v1/posts/{post_id}"

List All Posts

curl "http://localhost:8000/api/v1/posts?from_=0&size=10&status_filter=published"

Elasticsearch Features Demonstrated

1. Full-Text Search

  • Multi-field search across title and content
  • Field boosting (title matches score higher)
  • Fuzzy matching for typo tolerance

2. Filtering

  • Filter by tags (exact match)
  • Filter by author (keyword match)
  • Filter by status (term match)

3. Relevance Scoring

  • Best fields matching
  • Score-based sorting combined with date sorting

4. Index Management

  • Custom index mappings
  • Text and keyword field types
  • Date and integer fields

5. Analytics

  • View count tracking
  • Document update with scripts

Testing the Search

Run the test search script to see search functionality in action:

uv run python test_search.py

This will test various search queries and show the results with highlighting.

Exploring with Kibana

Access Kibana at http://localhost:5601 to:

  1. View your blog posts index
  2. Run custom Elasticsearch queries
  3. Visualize search analytics
  4. 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"
    }
  }
}

Key Concepts Explained

Elasticsearch Mappings

The index uses custom mappings to optimize search:

{
    "title": {
        "type": "text",        # Full-text search
        "fields": {
            "keyword": {       # Exact match filtering
                "type": "keyword"
            }
        }
    }
}

Multi-Match Query

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
    }
}

Bool Query

Combine multiple query conditions:

{
    "bool": {
        "must": [/* queries that must match */],
        "filter": [/* queries that filter results */]
    }
}

Development Tips

Reset the Index

curl -X DELETE "http://localhost:9200/blog_posts"
uv run python seed_data.py

View All Documents

curl "http://localhost:9200/blog_posts/_search?pretty"

Check Index Mapping

curl "http://localhost:9200/blog_posts/_mapping?pretty"

Monitor Elasticsearch

curl "http://localhost:9200/_cluster/health?pretty"

Common Issues and Solutions

Elasticsearch not starting

  • Make sure Docker is running
  • Check if ports 9200 and 9300 are available
  • Increase Docker memory allocation (Settings β†’ Resources)

Connection refused

  • Wait a minute after starting docker-compose
  • Check Elasticsearch logs: docker-compose logs elasticsearch

Import errors

  • Make sure you installed dependencies: uv sync
  • uv automatically creates and manages virtual environments
  • Always use uv run to execute scripts in the project environment

No search results

  • Run python seed_data.py to populate data
  • Check if index exists: curl http://localhost:9200/_cat/indices

Package Management with uv

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.py

Learn More

License

MIT License - Feel free to use this project for learning and development.

Contributing

This is a tutorial project, but suggestions and improvements are welcome!


Happy Searching! πŸ”

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages