# Fractal Projections
> A comprehensive projection system for defining how data should be shaped, aggregated, grouped, ordered, and limited in database queries.
[![PyPI Version][pypi-image]][pypi-url]
[![Build Status][build-image]][build-url]
<!-- Badges -->
[pypi-image]: https://img.shields.io/pypi/v/fractal-projections
[pypi-url]: https://pypi.org/project/fractal-projections/
[build-image]: https://github.com/Fractal-Forge/fractal-projections/actions/workflows/build.yml/badge.svg
[build-url]: https://github.com/Fractal-Forge/fractal-projections/actions/workflows/build.yml
This library complements [fractal-specifications](https://pypi.org/project/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
- MongoDB
- Firestore
- Elasticsearch
## Installation
```bash
pip install fractal-projections
```
For specific database support:
```bash
# PostgreSQL
pip install fractal-projections[postgres]
# 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
```python
from fractal_projections import (
QueryProjection,
FieldProjection,
ProjectionList,
OrderingProjection,
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=OrderingProjection("created_at", descending=True),
limit=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 = $1 ORDER BY created_at DESC LIMIT 10
```
## Core Concepts
### Field Projection
Select specific fields from your data:
```python
from fractal_projections import FieldProjection, ProjectionList
projection = ProjectionList([
FieldProjection("user_id"),
FieldProjection("email"),
])
```
### Aggregation
Perform aggregations like COUNT, SUM, AVG:
```python
from fractal_projections import AggregateProjection, AggregateFunction
projection = AggregateProjection(
field="revenue",
function=AggregateFunction.SUM,
alias="total_revenue"
)
```
### Grouping
Group results by one or more fields:
```python
from fractal_projections import GroupingProjection
grouping = GroupingProjection(["organization_id", "status"])
```
### Ordering
Sort results by fields:
```python
from fractal_projections import OrderingProjection, OrderingList
ordering = OrderingList([
OrderingProjection("created_at", descending=True),
OrderingProjection("name", descending=False),
])
```
### Limiting
Limit and offset results:
```python
from fractal_projections import LimitProjection
limit = LimitProjection(limit=20, offset=10)
```
## Architecture
The library follows a builder pattern:
1. **Projections**: Database-agnostic definitions of how data should be shaped
2. **Builders**: Database-specific converters that translate projections into native queries
```
QueryProjection (agnostic)
↓
PostgresProjectionBuilder → 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
## Advanced Usage
See the [examples.py](fractal_projections/examples.py) file for comprehensive examples including:
- Complex aggregations with grouping
- Multi-field ordering
- Combining filters with projections
- Database-specific optimizations
## Development
```bash
# 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-projections](https://github.com/Fractal-Forge/fractal-projections) - Database-agnostic filtering system
Raw data
{
"_id": null,
"home_page": null,
"name": "fractal-projections",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "database, query, projection, aggregation, sql, mongodb, firestore, elasticsearch",
"author": null,
"author_email": "Douwe van der Meij <douwe@karibu-online.nl>",
"download_url": "https://files.pythonhosted.org/packages/c7/ff/0acead8b80aceefc892b73a5a5dcdff09ab52e9d52e770ab336cc5cf2f90/fractal_projections-0.1.0.tar.gz",
"platform": null,
"description": "# Fractal Projections\n\n> A comprehensive projection system for defining how data should be shaped, aggregated, grouped, ordered, and limited in database queries.\n\n[![PyPI Version][pypi-image]][pypi-url]\n[![Build Status][build-image]][build-url]\n\n<!-- Badges -->\n\n[pypi-image]: https://img.shields.io/pypi/v/fractal-projections\n[pypi-url]: https://pypi.org/project/fractal-projections/\n[build-image]: https://github.com/Fractal-Forge/fractal-projections/actions/workflows/build.yml/badge.svg\n[build-url]: https://github.com/Fractal-Forge/fractal-projections/actions/workflows/build.yml\n\nThis library complements [fractal-specifications](https://pypi.org/project/fractal-specifications/) (which handles filtering) by providing database-agnostic data shaping capabilities.\n\n## Features\n\n- **Database-Agnostic**: Write projections once, use them across different databases\n- **Type-Safe**: Fully typed Python API for better IDE support and fewer errors\n- **Flexible**: Support for field selection, aggregations, grouping, ordering, and limiting\n- **Multi-Database Support**: Built-in builders for:\n - PostgreSQL\n - MongoDB\n - Firestore\n - Elasticsearch\n\n## Installation\n\n```bash\npip install fractal-projections\n```\n\nFor specific database support:\n\n```bash\n# PostgreSQL\npip install fractal-projections[postgres]\n\n# MongoDB\npip install fractal-projections[mongo]\n\n# Firestore\npip install fractal-projections[firestore]\n\n# Elasticsearch\npip install fractal-projections[elasticsearch]\n\n# All databases\npip install fractal-projections[all]\n```\n\n## Quick Start\n\n```python\nfrom fractal_projections import (\n QueryProjection,\n FieldProjection,\n ProjectionList,\n OrderingProjection,\n LimitProjection,\n)\nfrom fractal_projections.builders import PostgresProjectionBuilder\nfrom fractal_specifications.generic.operators import EqualsSpecification\n\n# Define a database-agnostic projection\nquery = QueryProjection(\n filter=EqualsSpecification(\"status\", \"active\"),\n projection=ProjectionList([\n FieldProjection(\"id\"),\n FieldProjection(\"name\"),\n FieldProjection(\"created_at\"),\n ]),\n ordering=OrderingProjection(\"created_at\", descending=True),\n limit=LimitProjection(10),\n)\n\n# Convert to database-specific query\nbuilder = PostgresProjectionBuilder(\"users\")\nsql, params = builder.build(query)\nprint(sql)\n# SELECT id, name, created_at FROM users WHERE status = $1 ORDER BY created_at DESC LIMIT 10\n```\n\n## Core Concepts\n\n### Field Projection\n\nSelect specific fields from your data:\n\n```python\nfrom fractal_projections import FieldProjection, ProjectionList\n\nprojection = ProjectionList([\n FieldProjection(\"user_id\"),\n FieldProjection(\"email\"),\n])\n```\n\n### Aggregation\n\nPerform aggregations like COUNT, SUM, AVG:\n\n```python\nfrom fractal_projections import AggregateProjection, AggregateFunction\n\nprojection = AggregateProjection(\n field=\"revenue\",\n function=AggregateFunction.SUM,\n alias=\"total_revenue\"\n)\n```\n\n### Grouping\n\nGroup results by one or more fields:\n\n```python\nfrom fractal_projections import GroupingProjection\n\ngrouping = GroupingProjection([\"organization_id\", \"status\"])\n```\n\n### Ordering\n\nSort results by fields:\n\n```python\nfrom fractal_projections import OrderingProjection, OrderingList\n\nordering = OrderingList([\n OrderingProjection(\"created_at\", descending=True),\n OrderingProjection(\"name\", descending=False),\n])\n```\n\n### Limiting\n\nLimit and offset results:\n\n```python\nfrom fractal_projections import LimitProjection\n\nlimit = LimitProjection(limit=20, offset=10)\n```\n\n## Architecture\n\nThe library follows a builder pattern:\n\n1. **Projections**: Database-agnostic definitions of how data should be shaped\n2. **Builders**: Database-specific converters that translate projections into native queries\n\n```\nQueryProjection (agnostic)\n \u2193\nPostgresProjectionBuilder \u2192 SQL\nMongoProjectionBuilder \u2192 MongoDB Pipeline\nFirestoreProjectionBuilder \u2192 Firestore Query\nElasticsearchProjectionBuilder \u2192 ES Query DSL\n```\n\nThis separation allows you to:\n- Write business logic once\n- Switch databases without changing application code\n- Get optimized native queries for each backend\n\n## Advanced Usage\n\nSee the [examples.py](fractal_projections/examples.py) file for comprehensive examples including:\n- Complex aggregations with grouping\n- Multi-field ordering\n- Combining filters with projections\n- Database-specific optimizations\n\n## Development\n\n```bash\n# Clone the repository\ngit clone https://github.com/Fractal-Forge/fractal-projections.git\ncd fractal-projections\n\n# Install development dependencies\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Format code\nblack .\nisort .\nruff check --fix .\n\n# Lint code\nruff check .\nmypy fractal_projections\n```\n\n## License\n\nMIT License - see LICENSE file for details\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Related Projects\n\n- [fractal-projections](https://github.com/Fractal-Forge/fractal-projections) - Database-agnostic filtering system",
"bugtrack_url": null,
"license": null,
"summary": "A comprehensive projection system for defining how data should be shaped, aggregated, grouped, ordered, and limited in database queries",
"version": "0.1.0",
"project_urls": {
"Documentation": "https://github.com/Fractal-Forge/fractal-projections#readme",
"Homepage": "https://github.com/Fractal-Forge/fractal-projections",
"Issues": "https://github.com/Fractal-Forge/fractal-projections/issues",
"Repository": "https://github.com/Fractal-Forge/fractal-projections"
},
"split_keywords": [
"database",
" query",
" projection",
" aggregation",
" sql",
" mongodb",
" firestore",
" elasticsearch"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "bc1cb009a0b978e15091f12d8a7232a5672e392a03f37e9bc3d4e1617aa9ac7e",
"md5": "275cae4966b734a361fff1e56e8d2a99",
"sha256": "98afef7c4595fa983cb0e1a608be97d63823137f980e62d946d653bee6dbe8d6"
},
"downloads": -1,
"filename": "fractal_projections-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "275cae4966b734a361fff1e56e8d2a99",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 19504,
"upload_time": "2025-10-21T16:40:10",
"upload_time_iso_8601": "2025-10-21T16:40:10.797338Z",
"url": "https://files.pythonhosted.org/packages/bc/1c/b009a0b978e15091f12d8a7232a5672e392a03f37e9bc3d4e1617aa9ac7e/fractal_projections-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c7ff0acead8b80aceefc892b73a5a5dcdff09ab52e9d52e770ab336cc5cf2f90",
"md5": "68e67665f2f46e12c700aba978093b6f",
"sha256": "33775e57fe97b0b6213a5a27c38c0c596cbbb37e3820bd454aa7eb485c52428b"
},
"downloads": -1,
"filename": "fractal_projections-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "68e67665f2f46e12c700aba978093b6f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 24754,
"upload_time": "2025-10-21T16:40:12",
"upload_time_iso_8601": "2025-10-21T16:40:12.306620Z",
"url": "https://files.pythonhosted.org/packages/c7/ff/0acead8b80aceefc892b73a5a5dcdff09ab52e9d52e770ab336cc5cf2f90/fractal_projections-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-21 16:40:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Fractal-Forge",
"github_project": "fractal-projections#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "fractal-projections"
}