Skip to main content

MoleQL logo

MoleQL

Expressive URL-query to MongoDB query conversion library.

CI License PyPI Python Versions

Overview

MoleQL allows your REST APIs or data layers to accept URL-style query strings (e.g. ?age>30&status=in(active,pending)) and converts them into MongoDB-compatible query dictionaries. It supports filters, sorting, skip/limit, projection and text search.

Example:

from moleql import parse

query = parse("age>30&country=US&name=/^John/i")
# yields:
# {
#   "filter": {"age": {"$gt": 30}, "country": "US", "name": {"$regex": "^John", "$options": "i"}},
#   "sort": None,
#   "skip": 0,
#   "limit": 0,
#   "projection": None
# }

✨ Features

  • 🧠 Intuitive syntax: =, !=, <, <=, >, >=
  • 📋 List operators: in(...), ...
  • 🔍 Regex: /pattern/flags → $regex + $options
  • 🧾 Pagination: skip=10, limit=50
  • ⚙️ Sorting: sort=-created_at,name
  • 🧩 Projection: fields=name,email,age
  • 🔠 Text search: text=free text here or $text=free text here
  • 🧱 Type casters: custom value transformations
  • 🚫 Blacklist: skip parsing of restricted fields
  • 🧪 Tested: full pytest coverage, Ruff linting

🧰 Installation

With uv (recommended):

uv add moleql
pip install moleql

🚀 Quick Start

from moleql import parse

query = parse("age>30&country=US&name=/^John/i")
print(query)

# {
#   "filter": {
#       "age": {"$gt": 30},
#       "country": "US",
#       "name": {"$regex": "^John", "$options": "i"}
#   },
#   "sort": None,
#   "skip": 0,
#   "limit": 0,
#   "projection": None
# }

Extended example

from moleql import parse

query = parse(
    "age>=18&status=in(active,pending)"
    "&sort=-created_at,name"
    "&skip=10&limit=20"
    "&fields=name,email,age"
)

Output:

{
    "filter": {
        "age": {"$gte": 18},
        "status": {"$in": ["active", "pending"]}
    },
    "sort": [("created_at", -1), ("name", 1)],
    "skip": 10,
    "limit": 20,
    "projection": {"name": 1, "email": 1, "age": 1}
}

🔣 Supported Operators

Expression Mongo Operator Example
= direct match age=20 → {"age": 20}
!= $ne status!=active
> / >= $gt / $gte score>=80
< / <= $lt / $lte price<10
in(...) $in role=in(admin,user)
!=in(...) $nin tier!=in(gold,platinum)
/pattern/flags $regex name=/^Jo/i
text= or $text= $text text=free search text
fields= projection fields=name,email
sort= sort directive sort=-created_at,name

🧱 Quick API Reference

parse(moleql_query: str, blacklist=None, casters=None) -> dict

from moleql import parse

parse("age>25&active=true")

Returns a dictionary with: filter, sort, skip, limit, projection

moleqularize(moleql_query: str, blacklist=None, casters=None) -> MoleQL

Parse a MoleQL string and return the internal MoleQL object for advanced inspection and debugging.

from moleql import moleqularize

m = moleqularize("age>25")
print(m.mongo_query)

🧩 Custom Casters

You can define custom casters to control type conversions.

from moleql import parse, get_casters


def to_bool(value: str) -> bool:
    return value.lower() in ("true", "1", "yes")


custom_casters = {"bool": to_bool}

q = parse("active=bool(true)&age>30", casters=custom_casters)

🧠 Design Philosophy

  • Transparency — The query string is readable and reversible.
  • Safety — No eval, injection-safe parsing.
  • Extensibility — Easy to plug in custom handlers.
  • Predictability — Every operator maps 1:1 to Mongo semantics.
  • Minimal dependencies — Pure Python, no ODM required.

⚙️ Integration Examples

FastAPI

from fastapi import FastAPI, Request
from moleql import parse
from pymongo import MongoClient

db = MongoClient()["app"]
app = FastAPI()


@app.get("/users")
def list_users(request: Request):
    q = parse(request.url.query.lstrip("?"))
    return list(db.users.find(q["filter"]))

Flask

from flask import Flask, request, jsonify
from moleql import parse

app = Flask(__name__)


@app.get("/orders")
def orders():
    q = parse(request.query_string.decode())
    return jsonify(q)

🧪 Testing

Run the full suite using uv:

uv sync --all-extras --dev
uv run pytest -vv --cov=moleql --cov-report=term-missing --cov-fail-under=100

Generate coverage:

uv run pytest --cov=moleql --cov-report=term-missing --cov-fail-under=100

🧹 Code Quality

This repository uses:

  • Ruff — Linting + formatting (UP / pyupgrade rules)
  • pre-commit — automatic checks
  • pytest — testing
  • uv — environment & packaging

Set up hooks:

uv run pre-commit install
uv run pre-commit run --all-files

🧭 Roadmap

  • [] Add exists(field) and between(a,b) operators
  • [] Add optional CLI (moleql "age>20" --as-json)
  • [] Extended docs and tutorials

🤝 Contributing

  1. Fork this repository

  2. Create your feature branch

    git checkout -b feat/awesome-change
    
  3. Run formatting and tests

    uv run pre-commit run --all-files
    uv run pytest
    
  4. Commit and push your changes

  5. Open a Pull Request 🚀

See CODE_OF_CONDUCT.md for details.

🌟 Acknowledgments

Built and maintained by @OneTesseractInMultiverse Inspired by the need for readable, typed, and safe Mongo queries in API environments.

Metadata

Release files for moleql 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for moleql 0.2.0
File Size Uploaded
moleql-0.2.0.tar.gz 12.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for moleql 0.2.0
File Interpreter ABI Platform
moleql-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 31.1 kB

Release files / moleql-0.2.0.tar.gz

Download URL moleql-0.2.0.tar.gz
Size 12.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e1bea84086e432a7f295473fa0c5ebb3d6806d29c3be6cb1d0f390dac9e2a617
BLAKE2b-256 checksum
How to use checksums
ac3ff85e5cac78f9bf7a01c29c45db640d449f0f1ab831f7accd184abbfe136c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 11, 2026.

Transparency log

Release files / moleql-0.2.0-py3-none-any.whl

Download URL moleql-0.2.0-py3-none-any.whl
Size 18.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dae13a567f61834c7a8c31725adbe7725f0935817502e93fdc4bbc039b960cd7
BLAKE2b-256 checksum
How to use checksums
cadceed2cbbf2d4cc113ac8fd3b1065548a4c37f8d887b1beaf05af2f0a185bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

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