Skip to main content
milvusql logo

milvusql

A PEP 249 DBAPI (sync + async) for Milvus — parses/generates MilvusQL via sqlglot-milvus and executes the resulting AST against pymilvus.

PyPI Python PyPI Downloads License CI

📚 Documentation · PyPI · sqlglot-milvus


Why a DBAPI, not a client wrapper?

Feature milvusql raw pymilvus
Query surface SQL (MilvusQL) Python method calls
Parameterized queries :name binds ⚠️ manual dict-building
Standard Connection/Cursor (PEP 249)
Sync + async, same dispatch table ⚠️ separate MilvusClient/AsyncMilvusClient
Drop-in for SQLAlchemy / Django milvusql-sqlalchemy, milvusql-django
Auto-LOAD on first use, cached per connection manual load_collection()
Consistency-level fallback (per-connection default, per-query override) manual per-call

Writing MilvusQL instead of chaining pymilvus calls means the same SELECT ... ORDER BY embedding <=> :q LIMIT n string works whether it's typed by hand, generated by an ORM, or built by an LLM tool call — and it works the same way from cursor.execute() or await acursor.execute(), off one shared parser and dispatch table (translate.ast_to_pymilvus).

Installation

pip install milvusql

Quick start

import milvusql

conn = milvusql.connect(uri="./items.db")  # Milvus Lite, or a real server's URI
cur = conn.cursor()

cur.execute(
    """
    CREATE TABLE items (
        id BIGINT PRIMARY KEY AUTO_INCREMENT,
        embedding VECTOR(8),
        category VARCHAR(64)
    ) WITH (shards=1, consistency_level='Strong')
    """
)
cur.execute(
    "CREATE INDEX idx_embedding ON items (embedding) USING HNSW WITH (metric_type='COSINE')"
)
cur.executemany(
    "INSERT INTO items (embedding, category) VALUES (:embedding, :category)",
    [{"embedding": [0.1] * 8, "category": "book"}],
)

cur.execute("SELECT id FROM items WHERE category = :cat LIMIT 10", {"cat": "book"})
print(cur.fetchall())

cur.execute(
    "SELECT id FROM items ORDER BY embedding <=> :q LIMIT 5",
    {"q": [0.1] * 8},
)
print(cur.fetchall())

The same program, asyncio-native, over milvusql.aio (built on pymilvus.AsyncMilvusClient):

from milvusql import aio

conn = aio.connect(uri="./items.db")
cur = conn.cursor()

await cur.execute("SELECT id FROM items WHERE category = :cat", {"cat": "book"})
async for row in cur:
    print(row)

await conn.close()

API

milvusql.connect()

milvusql.connect(
    uri="http://localhost:19530",  # or a Milvus Lite file path
    token="",                      # "user:password", or a full token string
    db_name="",
    consistency_level=None,        # per-connection default; a query's own CONSISTENCY LEVEL wins
    **kwargs,                      # passed straight through to pymilvus.MilvusClient
) -> Connection
Connection Description
.cursor() Returns a new Cursor bound to this connection
.commit() No-op — every statement is already applied when it returns
.rollback() Raises NotSupportedError — Milvus has no multi-statement rollback; catch and compensate instead
.close() Closes the underlying MilvusClient
Context manager with milvusql.connect(...) as conn: ...
Cursor Description
.execute(operation, parameters=None) Runs one statement; parameters binds :name placeholders
.executemany(operation, seq_of_parameters) Batched INSERT in one round trip where the statement allows it; falls back to one call per parameter set otherwise
.fetchone() / .fetchmany(size) / .fetchall() Read back result rows
.description, .rowcount, .lastrowid, .arraysize Standard PEP 249 attributes
Iteration for row in cursor: ...

milvusql.aio.connect()/AsyncConnection/AsyncCursor mirror the same shape, async/await throughout — deliberately not PEP 249 itself (execute() as a coroutine can't be), but built on the same parser, dispatch table, and error hierarchy as the sync path.

Errors

Standard PEP 249 hierarchy, importable from milvusql:

Warning
Error
├── InterfaceError
└── DatabaseError
    ├── DataError
    ├── OperationalError
    ├── IntegrityError
    ├── InternalError
    ├── ProgrammingError
    └── NotSupportedError

Every pymilvus exception and gRPC error raised while executing a statement is translated into one of these before it reaches your code.

Packages

This is the core of a uv workspace. Two packages build on milvusql's DBAPI:

Package Description
milvusql-sqlalchemy SQLAlchemy 2.0 dialect — VECTOR/SPARSEVEC column types, hybrid_search(), Alembic support
milvusql-django Django database backend — VectorField, ORM CRUD/filtering through the normal compiler

Each is installed and versioned separately; both depend on this package as their DBAPI layer.

Examples

Example Shows
examples/basic_walkthrough A guided, top-to-bottom tour of the DBAPI: connect, CREATE TABLE/CREATE INDEX, insert, filter SELECT, vector search, UPDATE/DELETE — sync and async
examples/temporal_worker A Temporal workflow/activity that inserts rows into Milvus as a durable, retry-safe ingestion pipeline

See also milvusql-sqlalchemy's own examples (a FastAPI image-search service, a pydantic-ai agent).

Development

Requires Python 3.12+, uv, task.

task install           # uv sync --all-groups --all-packages
task lint              # ruff + ty + bandit for core + all packages
task tests             # all tests (core + sqlalchemy + django) -- integration tests need Docker (testcontainers)

Individual package tasks:

task core:lint         task core:test
task sqlalchemy:lint   task sqlalchemy:test
task django:lint       task django:test

License

MIT

Release files for milvusql 0.1.4

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

Source distribution (sdist)

Source distribution for milvusql 0.1.4
File Size Uploaded
milvusql-0.1.4.tar.gz 30.6 kB Details

Built distribution (wheel)

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

Total release size: 66.3 kB

Release files / milvusql-0.1.4.tar.gz

Download URL milvusql-0.1.4.tar.gz
Size 30.6 kB
Tags Source
SHA-256 checksum
How to use checksums
bcefcf7da06385dfc1c01faf2d294e377aad1ea62507b556646b0c2398eebd35
BLAKE2b-256 checksum
How to use checksums
bb0d65d966dfa31bd513616ebc447f133c87f59fcaab146d178c33dfd627b7bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / milvusql-0.1.4-py3-none-any.whl

Download URL milvusql-0.1.4-py3-none-any.whl
Size 35.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b19b02e9b65ac9ab75fa93b8a0eb21a21a5c0d44f679f2f02f0b9dd2f5f59a03
BLAKE2b-256 checksum
How to use checksums
81bd39806e51ca3fa0dac9c77d6c661c4974bcebffce7a3970f4bcb9a45a8154
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

1.0.0

2 release files

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

1 release file

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