Skip to main content

SQLAlchemy query filtering and sorting wrapper in JSON format.

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sqlalchemy-filtering-0.1.2.tar.gz (13.2 kB view details)

Uploaded Source

Built Distribution

sqlalchemy_filtering-0.1.2-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file sqlalchemy-filtering-0.1.2.tar.gz.

File metadata

  • Download URL: sqlalchemy-filtering-0.1.2.tar.gz
  • Upload date:
  • Size: 13.2 kB
  • Tags: Source
  • Uploaded using 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

File hashes

Hashes for sqlalchemy-filtering-0.1.2.tar.gz
Algorithm Hash digest
SHA256 7679daeaee4e07ab90e7f721498c4ae431db74596279545fa252361d3f2188a5
MD5 efbc7272af0a37870500f7aaf0099226
BLAKE2b-256 42d6a33a2dfa6a74c418403d9c16474ee4f88c1f021527979d599d12785c6f67

See more details on using hashes here.

File details

Details for the file sqlalchemy_filtering-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: sqlalchemy_filtering-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 13.0 kB
  • Tags: Python 3
  • Uploaded using 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

File hashes

Hashes for sqlalchemy_filtering-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0c0accce0ab86d84a583a47ca9862cd2e6e6a4e9c08fea84a7ba64569b9bc16c
MD5 4e3885c6d51fb8bab3964e3f6a9d74dc
BLAKE2b-256 4e87b80322534453536aa815f50ac619b68f4e7761603a773d8bdda2dedf89da

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page