A modern and scalable search engine built with FastAPI and RedisSearch, allowing you to create dynamic schemas and index documents for real-time search.
This is a simple yet powerful search engine solution designed for developers and small to medium-sized projects that need fast, full-text search capabilities without the complexity of enterprise search solutions.
The Search Engine provides a straightforward way to implement search functionality in your applications. Built with Python and RedisSearch, it offers:
- Simplicity: Easy to set up and use - just run Docker Compose and you're ready to go
- Flexibility: Create custom search schemas dynamically without database migrations
- Performance: Leverages RedisSearch for lightning-fast search operations
- Developer-Friendly: RESTful API with automatic interactive documentation
This solution is ideal for:
- Developers building applications that need search functionality (e-commerce, content management, document systems)
- Small to Medium Projects that require search capabilities without the overhead of complex search infrastructure
- Prototyping and MVP development where you need search features quickly
- Learning Projects to understand how search engines work under the hood
- Startups and small teams that need a cost-effective search solution
While there are more complex search solutions available (Elasticsearch, Solr, etc.), this engine focuses on simplicity and ease of use. If you need:
- Quick setup and deployment
- Simple API integration
- Full-text search with basic features
- A lightweight solution that doesn't require extensive configuration
Then this search engine is perfect for you. It's built with modern Python technologies (FastAPI) and RedisSearch, making it both performant and easy to maintain.
- Introduction
- About the Project
- Features
- Technologies
- Prerequisites
- Installation
- Configuration
- Usage
- API Reference
- Project Structure
- Examples
- Development
This project is a search engine that uses RedisSearch to provide full-text search capabilities on documents. It allows you to create dynamic schemas with different field types (text, numeric, tag) and index documents for fast and efficient searching.
- β Dynamic search schema creation
- β Document indexing with field validation
- β Full-text search with pagination
- β Support for multiple field types (text, numeric, tag)
- β Sortable fields and customizable weights
- β Automatically documented RESTful API
- β Clean architecture with separation of concerns
- β Consistent error handling
- FastAPI - Modern and fast web framework for APIs
- RedisSearch - Full-text search engine based on Redis
- Redis - In-memory database
- Pydantic - Data validation
- Docker - Containerization
- Python 3 - Programming language
- Docker and Docker Compose installed
- Git
- Clone the repository:
git clone https://github.com/FabioAugustoRodrigues/search-engine.git
cd search-engine- Start the services:
docker compose up -d-
The API will be available at
http://localhost:8400 -
Access the interactive documentation at:
- Swagger UI:
http://localhost:8400/docs - ReDoc:
http://localhost:8400/redoc
- Swagger UI:
That's it! The project is ready to use. All dependencies and services (FastAPI application and Redis with RedisSearch) are automatically configured and started via Docker Compose.
The project is pre-configured to work out of the box. The Redis connection is automatically set up between the containers.
If you need to customize the Redis connection URL, you can create a .env file in the project root:
REDIS_URL=redis://redis:6379Note: When using Docker Compose, the default configuration works without any additional setup.
First, you need to create a schema that defines the structure of the documents that will be indexed.
Endpoint: POST /api/v1/schemas
Request Example:
{
"name": "products",
"fields": [
{
"name": "name",
"type": "text",
"sortable": true,
"weight": 5.0
},
{
"name": "price",
"type": "numeric",
"sortable": true
},
{
"name": "category",
"type": "tag",
"sortable": false
}
]
}Field Types:
text: Text field for full-text searchnumeric: Numeric field for comparisons and sortingtag: Tag field for categorical filtering
Field Parameters:
name: Field name (required)type: Field type -text,numeric, ortag(required)sortable: Whether the field can be used for sorting (default:false)weight: Field weight in search (only fortext, default:1.0)
After creating the schema, you can index documents.
Endpoint: POST /api/v1/documents
Request Example:
{
"schema_name": "products",
"fields": {
"name": "Dell XPS 13 Laptop",
"price": 1299.99,
"category": "electronics"
}
}Important: The document fields must exactly match the fields defined in the schema.
Search documents using free text.
Endpoint: GET /api/v1/documents
Query Parameters:
schema_name(required): Schema nametext(required): Search textlimit(optional): Maximum number of results (default: 10)offset(optional): Number of results to skip (default: 0)
Example:
GET /api/v1/documents?schema_name=products&text=laptop&limit=10&offset=0
Response:
{
"details": {
"message": "Documents retrieved successfully",
"documents": {
"total": 1,
"documents": [
{
"id": "document-uuid",
"fields": {
"name": "Dell XPS 13 Laptop",
"price": 1299.99,
"category": "electronics"
},
"score": 1.5
}
]
}
},
"status_code": 200
}List all created schemas.
Endpoint: GET /api/v1/schemas
Creates a new search schema.
Request Body:
{
"name": "string (alphanumeric/underscore)",
"fields": [
{
"name": "string",
"type": "text | numeric | tag",
"sortable": boolean,
"weight": number (only for text)
}
]
}Responses:
200: Schema created successfully409: Schema already exists500: Error creating schema
Lists all created schemas.
Responses:
200: List of schemas
Indexes a new document.
Request Body:
{
"schema_name": "string",
"fields": {
"field1": "value1",
"field2": "value2"
}
}Responses:
200: Document indexed successfully400: Invalid fields (extra or missing fields)404: Schema not found
Searches documents by text.
Query Parameters:
schema_name(string, required)text(string, required)limit(integer, optional, default: 10)offset(integer, optional, default: 0)
Responses:
200: Documents found404: Schema not found
search-engine/
βββ app/
β βββ api/
β β βββ v1/
β β βββ document.py # Document routes
β β βββ schema.py # Schema routes
β βββ core/
β β βββ clients.py # Redis client
β β βββ dependencies.py # Dependency injection
β β βββ responses.py # Standardized responses
β β βββ settings.py # Settings
β βββ domain/
β β βββ exceptions/
β β β βββ domain_exception.py # Domain exceptions
β β βββ services/
β β βββ document_service.py # Business logic - documents
β β βββ schema_service.py # Business logic - schemas
β βββ infrastructure/
β β βββ providers/
β β βββ redis_provider.py # Basic Redis provider
β β βββ redis_search_provider.py # RedisSearch provider
β βββ schemas/
β β βββ document.py # Pydantic models - documents
β β βββ schema.py # Pydantic models - schemas
β βββ validators/
β βββ fields_validator.py # Field validator
βββ docker/
β βββ Dockerfile.Python.Dev # Development Dockerfile
βββ compose.yml # Docker Compose
βββ main.py # Application entry point
βββ README.md # Documentation
The project follows a layered architecture:
- API Layer (
app/api/): REST endpoints and routes - Domain Layer (
app/domain/): Business logic and exceptions - Infrastructure Layer (
app/infrastructure/): Provider implementations (Redis, RedisSearch) - Core (
app/core/): Settings, dependencies, and shared utilities
- Create Schema:
curl -X POST "http://localhost:8400/api/v1/schemas" \
-H "Content-Type: application/json" \
-d '{
"name": "products",
"fields": [
{"name": "title", "type": "text", "sortable": true, "weight": 10.0},
{"name": "description", "type": "text", "sortable": false, "weight": 2.0},
{"name": "price", "type": "numeric", "sortable": true},
{"name": "category", "type": "tag", "sortable": true},
{"name": "brand", "type": "tag", "sortable": false}
]
}'- Index Products:
curl -X POST "http://localhost:8400/api/v1/documents" \
-H "Content-Type: application/json" \
-d '{
"schema_name": "products",
"fields": {
"title": "Samsung Galaxy S23 Smartphone",
"description": "Android smartphone with 256GB storage",
"price": 899.99,
"category": "electronics",
"brand": "samsung"
}
}'- Search Products:
curl "http://localhost:8400/api/v1/documents?schema_name=products&text=samsung&limit=5"- Create Schema:
{
"name": "articles",
"fields": [
{"name": "title", "type": "text", "sortable": true, "weight": 8.0},
{"name": "content", "type": "text", "sortable": false, "weight": 1.0},
{"name": "author", "type": "tag", "sortable": true},
{"name": "published_date", "type": "numeric", "sortable": true}
]
}- Index Article:
{
"schema_name": "articles",
"fields": {
"title": "Introduction to FastAPI",
"content": "FastAPI is a modern framework for building APIs...",
"author": "john_doe",
"published_date": 20240115
}
}- Clean Architecture: Clear separation between layers
- Dependency Injection: Use of FastAPI dependencies
- Domain-Driven Design: Domain services encapsulate business logic
- Provider Pattern: Infrastructure abstraction through providers
- Fork the project
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License. See the LICENSE file for more details.
Fabio Augusto Rodrigues - @FabioAugustoRodrigues
- FastAPI for the excellent documentation
- RedisSearch for the powerful search engine
- Open source community