Skip to main content

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:

  1. ID: id (type: integer)
  2. 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
    }
  ]
}
  1. 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_null
  • is_not_null
  • > (alias: gt)
  • < (alias: lt)
  • >= (alias: ge)
  • <= (alias: le)
  • like
  • not_like
  • ilike
  • not_ilike
  • in
  • not_in
  • contains
  • any
  • match
  • starts_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)

Source distribution for sqlalchemy-filtering 0.1.2
File Size Uploaded
sqlalchemy-filtering-0.1.2.tar.gz 13.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqlalchemy-filtering 0.1.2
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page