Skip to main content

A Lucene query like fliltering for SQLModel

Project description

sqlmodel-filters

PyPI version Test

A Lucene query like filter for SQLModel.

[!NOTE] This is an alpha level library. Everything is subject to change & there are some known limitations.

Installation

pip install sqlmodel-filters

How to Use

Let's say we have the following model & records:

import datetime
from functools import partial
from typing import Optional

from sqlmodel import Field, SQLModel


class Hero(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    secret_name: str
    age: Optional[int] = None
    created_at: datetime.datetime = Field(
        default_factory=partial(datetime.datetime.now, datetime.UTC)
    )

hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)


engine = create_engine("sqlite://")


SQLModel.metadata.create_all(engine)

with Session(engine) as session:
    session.add(hero_1)
    session.add(hero_2)
    session.add(hero_3)
    session.commit()

And let's try querying with this library.

# this library relies on luqum (https://github.com/jurismarches/luqum) for parsing Lucene query
from luqum import parse
from sqlmodel import Session

from sqlmodel_filters import SelectBuilder

# parse a Lucene query
parsed = parse('name:Spider')
# build SELECT statement for Hero based on the parsed query
builder = SelectBuilder(Hero)
statement = builder(parsed)

# the following is a compiled SQL query
statement.compile(compile_kwargs={"literal_binds": True})
>>> SELECT hero.id, hero.name, hero.secret_name, hero.age, hero.created_at
>>> FROM hero
>>> WHERE hero.name = '%Spider%'

# you can use the statement like this
heros = session.exec(statement).all()
assert len(heros) == 1
assert heros[0].name == "Spider-Boy"

Note that a value is automatically casted based on a field of the model.

# age: Optional[int]
"age:48"
>>> WHERE hero.age = 48

# created_at: datetime.datetime
"created_at:2020-01-01"
>>> WHERE hero.created_at = '2020-01-01 00:00:00'

Word (Term)

Double quote a value if you want to use the equal operator.

'name:"Spider-Boy"'
>>> WHERE hero.name = 'Spider-Boy'

The LIKE operator is used when you don't double quote a value.

"name:Spider"
>>> WHERE hero.name LIKE '%Spider%'

Use ? (a single character wildcard) or * (a multiple character wildcard) to control a LIKE operator pattern.

"name:Deadpond?"
>>> WHERE hero.name LIKE 'Deadpond_'

"name:o*"
>>> WHERE hero.name LIKE 'o%'

FROM & TO

"age:>=40"
>>> WHERE hero.age >= 40

"age:>40"
>>> WHERE hero.age > 40
"age:<=40"
>>> WHERE hero.age <= 40

"age:<40"
>>> WHERE hero.age < 40

RANGE

"age:{48 TO 60}"
>>> WHERE hero.age < 60 AND hero.age > 48

"age:[48 TO 60]"
>>> WHERE hero.age <= 60 AND hero.age >= 48

AND, OR, NOT and GROUP (Grouping)

"name:Rusty AND age:48"
>>> WHERE hero.name LIKE '%Rusty%' AND hero.age = 48

"name:Rusty OR age:47"
>>> WHERE hero.name LIKE '%Rusty%' OR hero.age = 47

"name:Rusty NOT age:47"
>>> WHERE hero.name LIKE '%Rusty%' AND hero.age != 47

"(name:Spider OR age:48) AND name:Rusty"
>>> WHERE (hero.name LIKE '%Spider%' OR hero.age = 48) AND hero.name LIKE '%Rusty%'

Tips

Selecting Columns

You can select columns by specifying entities.

tree = parse("name:*")
statement = builder(tree, entities=(Hero.id, Hero.name))

session.exec(statement).all()
>>> [(1, "Deadpond"), (2, "Spider-Boy"), (3, "Rusty-Man")]

Function

Also you can use a function such as count.

tree = parse("name:*")
statement = builder(tree, entities=func.count(Hero.id))

session.scalar(statement)
>>> 3

Known Limitations / Todos

  • Relationship join is not supported
  • Field Grouping is not supported

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

sqlmodel_filters-0.0.2.tar.gz (5.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sqlmodel_filters-0.0.2-py3-none-any.whl (6.9 kB view details)

Uploaded Python 3

File details

Details for the file sqlmodel_filters-0.0.2.tar.gz.

File metadata

  • Download URL: sqlmodel_filters-0.0.2.tar.gz
  • Upload date:
  • Size: 5.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.10.12 Linux/6.5.0-1016-azure

File hashes

Hashes for sqlmodel_filters-0.0.2.tar.gz
Algorithm Hash digest
SHA256 c55c46f0f015997c06619c94e1d79a6ffa2cf0a8c3c070450fd5afdabb444c8a
MD5 84ba955296d105365980f2808a0ecc97
BLAKE2b-256 af5bf2bef08c6ff38fcc26cf5d3393348258e0469e1dc71478eeeaa2faa19a03

See more details on using hashes here.

File details

Details for the file sqlmodel_filters-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: sqlmodel_filters-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 6.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.10.12 Linux/6.5.0-1016-azure

File hashes

Hashes for sqlmodel_filters-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 18cb5033afbae7e50d2911814487e7123610cbf8a84be33d9a7bb455f943ee66
MD5 7b7852a22ba7a1155ba07ab3631f68b7
BLAKE2b-256 5c6dcbb594040473d23d03be25642935579b8f42d3d4b25eb7dbb86753707185

See more details on using hashes here.

Supported by

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