SQLAlchemy filtering & sorting utility
Table of contents
Purpose
This repository was developed to provide a simple JSON format interface to the SQLAlchemy
query API to query on json SQL fields, which can be used by front-end applications to generate automatically SQL filtering queries
with minimum effort in the back-end service implementation.
Features
Some of the sqlalchemy-filtering utility features include:
| Category | Feature | PostgreSQL | MySQL | SQLite |
|---|---|---|---|---|
| Filtering | Ability to filter simple SQL fields | Yes | Yes | Yes |
Ability to filter json SQL fields |
Yes | Yes (Beta) | No | |
| Ability to filter join queries | No | No | No | |
| Sorting | Ability to sort simple SQL fields | Yes | Yes | Yes |
Ability to sort json SQL fields |
Yes | Yes (Beta) | No | |
| Ability to sort on joined fields | No | No | No |
Usage
Given the following SQLAlchemy models:
from sqlalchemy import Column, Integer, String, DateTime, Float
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import functions
Base = declarative_base()
class UserInfo(Base):
__tablename__ = "user_info"
id = Column(Integer, primary_key=True, index=True)
details = Column(JSONB)
creation_date = Column(DateTime, nullable=False, server_default=functions.now())
class Ratings(Base):
__tablename__ = "ratings"
id = Column(Integer, primary_key=True, index=True)
creation_date = Column(DateTime, nullable=False, server_default=functions.now())
movie_name = Column(String)
rating = Column(Float)
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tests import models
engine = create_engine(
'postgresql://postgres:password@localhost:5432/filter'
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()
query = db.query(models.UserInfo)
Assuming we have records in the database with the following structure:
- ID:
id(type: integer) - Details:
details(type: json)
{
"skin": "White",
"extra": {
"test": "value"
},
"gender": "Male",
"height": 188,
"last_name": "Walker",
"first_name": "Paul",
"user_details": [
{
"skill": "Fighting",
"rating": 7
},
{
"skill": "Driving",
"rating": 10
}
]
}
- Creation date:
creation_date(type: timestamp)
Filtering
# Case 1: Flat request on JSON column
obj = {
"filter": [
{
## (PostgreSQL) It returns all users that have skill 'Fighting' with rating 10
"field": "details",
"node": "user_details",
"operator": "@>",
"value": "[{\"skill\":\"Fighting\",\"rating\":10}]",
},
{
## (PostgreSQL) It returns all users that have skill 'Fighting' and any rating (in any skill) with rating 10
"field": "details",
"node": "user_details",
"operator": "@>",
"value": "[{\"skill\":\"Fighting\"},{\"rating\":10}]",
}
]
}
# Case2: Nested request in JSON nodes
obj = {
"filter": [
{
"field": "details",
"node": "extra",
"value": {
"field": "test",
"operator": "==",
"value": "value"
}
}
]
}
from sqlalchemy_filtering.filter_util import filter_apply
from sqlalchemy_filtering.operators import SQLDialect
from sqlalchemy_filtering.validators import FilterRequest
from tests import models
query = filter_apply(query=query, entity=models.UserInfo, obj=FilterRequest(obj), dialect=SQLDialect.POSTGRESQL)
Filtering operators
Filtering operators AND (and_), OR (or_) and NOT (not_) are supported and can be used all together.
obj3 = {
"filter": {
"not": [
{
"field": "movie_name",
"operator": "==",
"value": "The Dark Knight"
},
{
"field": "rating",
"operator": "==",
"value": 7
}
]
}
}
Sorting
# Case 1: Sort request on JSON column
obj = {
"sort": [
{
"field": "details",
"node": "height",
"direction": "desc",
"nullsLast": True
}
]
}
# Case 2: Sort request on inner JSON node column
obj = {
"sort": [
{
"field": "details",
"node": "extra.test",
"direction": "desc",
"nullsLast": True
}
]
}
# Case 3: Sort request on simple column
obj = {
"sort": [
{
"field": "creation_date",
"direction": "desc",
"nullsLast": True
}
]
}
from sqlalchemy_filtering.sort_util import sort_apply
from sqlalchemy_filtering.validators import SortRequest
from tests import models
query = sort_apply(query=query, entity=models.UserInfo, obj=SortRequest(obj))
Comparison operators
The list of the available comparison operators can be found below:
is(aliases:==,eq)is_not(aliases:!=,ne)is_nullis_not_null>(alias:gt)<(alias:lt)>=(alias:ge)<=(alias:le)likenot_likeilikenot_ilikeinnot_incontainsanymatchstarts_with
PostgreSQL specific JSON operators
@><@@?@@
Versions tested
| System | Version |
|---|---|
| PostgreSQL | 9.2, 12.7 |
| MySQL | 8.0.20, 8.0.27 |
| SQLite | 3.37 |
| SQLAlchemy | >= 1.4.0 |
Release files for sqlalchemy-filtering 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sqlalchemy-filtering-0.1.2.tar.gz | 13.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sqlalchemy_filtering-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.2 kB
Release files / sqlalchemy-filtering-0.1.2.tar.gz
| Download URL | sqlalchemy-filtering-0.1.2.tar.gz |
|---|---|
| Size | 13.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7679daeaee4e07ab90e7f721498c4ae431db74596279545fa252361d3f2188a5
|
|
BLAKE2b-256 checksum How to use checksums |
42d6a33a2dfa6a74c418403d9c16474ee4f88c1f021527979d599d12785c6f67
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10
|
Release files / sqlalchemy_filtering-0.1.2-py3-none-any.whl
| Download URL | sqlalchemy_filtering-0.1.2-py3-none-any.whl |
|---|---|
| Size | 13.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0c0accce0ab86d84a583a47ca9862cd2e6e6a4e9c08fea84a7ba64569b9bc16c
|
|
BLAKE2b-256 checksum How to use checksums |
4e87b80322534453536aa815f50ac619b68f4e7761603a773d8bdda2dedf89da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.7.1 importlib_metadata/4.10.0 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10
|