Fractal Projections
A comprehensive projection system for defining how data should be shaped, aggregated, grouped, ordered, and limited in database queries.
This library complements fractal-specifications (which handles filtering) by providing database-agnostic data shaping capabilities.
Features
- Database-Agnostic: Write projections once, use them across different databases
- Type-Safe: Fully typed Python API for better IDE support and fewer errors
- Flexible: Support for field selection, aggregations, grouping, ordering, and limiting
- Multi-Database Support: Built-in builders for:
- PostgreSQL
- Django ORM
- DuckDB
- MongoDB
- Firestore
- Elasticsearch
- Repository Integration: Ready-to-use mixins for fractal-repositories
Installation
pip install fractal-projections
For specific database support:
# PostgreSQL
pip install fractal-projections[postgres]
# Django ORM
pip install fractal-projections[django]
# DuckDB
pip install fractal-projections[duckdb]
# MongoDB
pip install fractal-projections[mongo]
# Firestore
pip install fractal-projections[firestore]
# Elasticsearch
pip install fractal-projections[elasticsearch]
# All databases
pip install fractal-projections[all]
Quick Start
from fractal_projections import (
QueryProjection,
FieldProjection,
ProjectionList,
OrderingProjection,
OrderingList,
LimitProjection,
)
from fractal_projections.builders import PostgresProjectionBuilder
from fractal_specifications.generic.operators import EqualsSpecification
# Define a database-agnostic projection
query = QueryProjection(
filter=EqualsSpecification("status", "active"),
projection=ProjectionList([
FieldProjection("id"),
FieldProjection("name"),
FieldProjection("created_at"),
]),
ordering=OrderingList([OrderingProjection("created_at", ascending=False)]),
limiting=LimitProjection(10),
)
# Convert to database-specific query
builder = PostgresProjectionBuilder("users")
sql, params = builder.build(query)
print(sql)
# SELECT id, name, created_at FROM users WHERE status = %s ORDER BY created_at DESC LIMIT 10
# params = ['active']
Core Concepts
Field Projection
Select specific fields from your data:
from fractal_projections import FieldProjection, ProjectionList
projection = ProjectionList([
FieldProjection("user_id"),
FieldProjection("email"),
])
Distinct Selection
Select unique values using the distinct parameter:
from fractal_projections import FieldProjection, ProjectionList
# SELECT DISTINCT department FROM users
projection = ProjectionList(
[FieldProjection("department")],
distinct=True
)
Aggregation
Perform aggregations using available aggregate functions: COUNT, SUM, AVG, MIN, MAX, COUNT_DISTINCT:
from fractal_projections import AggregateProjection, AggregateFunction, ProjectionList
# Single aggregate
projection = ProjectionList([
AggregateProjection(AggregateFunction.SUM, "revenue", "total_revenue")
])
# Multiple aggregates
projection = ProjectionList([
AggregateProjection(AggregateFunction.COUNT, alias="total_count"),
AggregateProjection(AggregateFunction.AVG, "salary", "avg_salary"),
AggregateProjection(AggregateFunction.MIN, "created_at", "earliest"),
AggregateProjection(AggregateFunction.MAX, "updated_at", "latest"),
AggregateProjection(AggregateFunction.COUNT_DISTINCT, "user_id", "unique_users"),
])
Grouping
Group results by one or more fields:
from fractal_projections import GroupingProjection
grouping = GroupingProjection(["organization_id", "status"])
Ordering
Sort results by fields:
from fractal_projections import OrderingProjection, OrderingList
ordering = OrderingList([
OrderingProjection("created_at", ascending=False), # descending
OrderingProjection("name", ascending=True), # ascending
])
Limiting
Limit and offset results:
from fractal_projections import LimitProjection
limit = LimitProjection(limit=20, offset=10)
Architecture
The library follows a builder pattern:
- Projections: Database-agnostic definitions of how data should be shaped
- Builders: Database-specific converters that translate projections into native queries
- Mixins: Repository mixins for seamless integration with fractal-repositories
QueryProjection (agnostic)
↓
PostgresProjectionBuilder → SQL
DjangoProjectionBuilder → Django QuerySet
DuckDBProjectionBuilder → SQL
MongoProjectionBuilder → MongoDB Pipeline
FirestoreProjectionBuilder → Firestore Query
ElasticsearchProjectionBuilder → ES Query DSL
This separation allows you to:
- Write business logic once
- Switch databases without changing application code
- Get optimized native queries for each backend
Repository Integration
Fractal Projections provides ready-to-use mixins for seamless integration with fractal-repositories. These mixins add projection capabilities to your repositories.
Available Mixins
PostgresProjectionsMixin- For PostgreSQL databasesDjangoProjectionsMixin- For Django ORMDuckDBProjectionsMixin- For DuckDB databasesMongoProjectionsMixin- For MongoDBFirestoreProjectionsMixin- For Firestore
Django Example
from fractal_repositories.contrib.django import DjangoModelRepositoryMixin
from fractal_projections import DjangoProjectionsMixin, QueryProjection, FieldProjection, ProjectionList
from fractal_specifications.generic.operators import EqualsSpecification
class UserRepository(DjangoModelRepositoryMixin, DjangoProjectionsMixin):
entity = User
django_model = DjangoUserModel
# Use the repository with projections
repo = UserRepository()
# Define a projection query
query = QueryProjection(
filter=EqualsSpecification("is_active", True),
projection=ProjectionList([
FieldProjection("id"),
FieldProjection("email"),
FieldProjection("username"),
]),
)
# Execute the query using the mixin
results = list(repo.find_with_projection(query))
# Returns: [{'id': 1, 'email': 'user@example.com', 'username': 'user1'}, ...]
# Count results
count = repo.count_with_projection(query)
# Get query explanation
explanation = repo.explain_query(query)
PostgreSQL Example
from fractal_repositories.contrib.postgres import PostgresRepositoryMixin
from fractal_projections import PostgresProjectionsMixin, QueryProjection
class ProductRepository(PostgresRepositoryMixin, PostgresProjectionsMixin):
entity = Product
table_name = "products"
repo = ProductRepository(connection)
results = list(repo.find_with_projection(query))
Mixin Methods
All projection mixins provide these methods:
find_with_projection(query_projection)- Execute query and return resultscount_with_projection(query_projection)- Count matching recordsexplain_query(query_projection)- Get query execution plan (for debugging/optimization)
Advanced Usage
See the examples.py file for comprehensive examples including:
- Complex aggregations with grouping
- Multi-field ordering
- Combining filters with projections
- Database-specific optimizations
Development
# Clone the repository
git clone https://github.com/Fractal-Forge/fractal-projections.git
cd fractal-projections
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
black .
isort .
ruff check --fix .
# Lint code
ruff check .
mypy fractal_projections
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Related Projects
- fractal-specifications - Database-agnostic filtering system
- fractal-repositories - Repository pattern implementation with projection support
Metadata
Release files for fractal-projections 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fractal_projections-0.3.1.tar.gz | 51.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fractal_projections-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 88.2 kB
Release files / fractal_projections-0.3.1.tar.gz
| Download URL | fractal_projections-0.3.1.tar.gz |
|---|---|
| Size | 51.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
27d880a52590f2a3d3a1e770e3700081a1dac2ecf6901d0b2da2eed25a714e16
|
|
BLAKE2b-256 checksum How to use checksums |
fd00cc5a9e8a90c87097748e73acd33223bb5c59577b88097196568ca12a3c9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.32.5
|
Release files / fractal_projections-0.3.1-py3-none-any.whl
| Download URL | fractal_projections-0.3.1-py3-none-any.whl |
|---|---|
| Size | 36.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a2f8665e327d8143529c8f35a5f3c00d412a30eae89c2082a355888aa42361cb
|
|
BLAKE2b-256 checksum How to use checksums |
a186d567ec84fd4a7d123bee5a57242bb39ee3572c2000e3e00e344d4a751597
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-requests/2.32.5
|
Security for fractal-projections 0.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.