Skip to main content

A generic Python ORM-like base class for building models backed by Xapiand

Project description

xapian_model

A generic Python ORM-like base class for building models backed by Xapiand, a distributed search engine. Part of the Dubalu Framework.

Features

  • Fully async — All Xapiand operations use async/await (powered by pyxapiand>=2.1.0 and httpx).
  • BaseXapianModel — Base class with attribute interception, save/delete operations, and template-based dynamic index naming.
  • Manager — Descriptor-based manager providing create(), get(), and filter() query methods.
  • SearchResults — Dataclass wrapping search results with total counts and aggregations.
  • Schema auto-provisioning — Automatically provisions the schema on first write.

Installation

pip install xapian-model

Dependencies

Requires pyxapiand 2.1.0+ (async client):

pip install "pyxapiand>=2.1.0"

Quick Start

import asyncio
from xapian_model.base import BaseXapianModel

class Product(BaseXapianModel):
    INDEX_TEMPLATE = "products/{store_id}"
    SCHEMA = {
        "name": {"_type": "text"},
        "price": {"_type": "float"},
        "active": {"_type": "boolean", "_default": True},
    }

async def main():
    # Create a product
    product = await Product.objects.create(store_id="store1", name="Widget", price=9.99)

    # Retrieve by ID
    product = await Product.objects.get(id="abc123", store_id="store1")

    # Search
    results = await Product.objects.filter(query="widget", store_id="store1", limit=10)
    for item in results.results:
        print(item.name, item.price)

    # Update and save
    product.price = 12.99
    await product.save()

    # Delete
    await product.delete()

asyncio.run(main())

Defining a Model

Subclass BaseXapianModel and define INDEX_TEMPLATE and SCHEMA:

  • INDEX_TEMPLATE — Format string for the Xapiand index path. Placeholders (e.g. {category}) are filled at runtime from keyword arguments passed to the manager methods.
  • SCHEMA — Dict describing the field types. Include _foreign to use a foreign schema stored at a separate path, and _type to declare the schema type.
from xapian_model.base import BaseXapianModel


class Product(BaseXapianModel):
    INDEX_TEMPLATE = "/products/{category}"
    SCHEMA = {
        "_type": "foreign/object",
        "_foreign": "/schemas/product",
        "name": {"_type": "text"},
        "price": {"_type": "float"},
        "tags": {"_type": "keyword"},
    }

On the first write Xapiand returns a 412 Precondition Failed because no schema exists yet. The Manager catches this and retries the request with _schema attached, which provisions the foreign schema automatically:

{
  "name": "Smartphone X",
  "price": 599.99,
  "tags": "mobile",
  "_schema": {
    "_type": "foreign/object",
    "_foreign": "schemas/product",
    "name": {"_type": "text"},
    "price": {"_type": "float"},
    "tags": {"_type": "keyword"}
  }
}

Subsequent writes to the same index hit Xapiand directly without the schema overhead.

CRUD operations

import asyncio


async def main():
    # Create
    product = await Product.objects.create(
        category="electronics",
        id="phone-1",
        name="Smartphone X",
        price=599.99,
        tags="mobile",
    )

    # Get by ID
    product = await Product.objects.get(id="phone-1", category="electronics")

    # Search
    results = await Product.objects.filter(category="electronics", query="Smartphone")
    for hit in results.results:
        print(hit.name, hit.price)

    # Update
    product.price = 499.99
    await product.save()

    # Delete
    await product.delete()


asyncio.run(main())

Requirements

License

MIT — Copyright (c) 2026 Dubalu International

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

xapian_model-0.4.1.tar.gz (16.1 kB view details)

Uploaded Source

Built Distribution

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

xapian_model-0.4.1-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file xapian_model-0.4.1.tar.gz.

File metadata

  • Download URL: xapian_model-0.4.1.tar.gz
  • Upload date:
  • Size: 16.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for xapian_model-0.4.1.tar.gz
Algorithm Hash digest
SHA256 b2321600857133275b876c08811b236ad43077108ee498cd15e31c47fb5efc32
MD5 138e42378a6667c1d0ae8936bcdcaed7
BLAKE2b-256 5e792c09a7f2f15ea1b483fd02e41b98ff310e6bde76c13520b005b3ffd08eae

See more details on using hashes here.

File details

Details for the file xapian_model-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: xapian_model-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for xapian_model-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c4db1ca28b870c9d8eb44385ebcb79ece206bf5a93c86b22b3139dce837e0824
MD5 21dcd55f885833a1388c0274c09deddf
BLAKE2b-256 4372a5958a56442051a6b54162c6c39902fb7d3424a5bae60cbcdeeb27a7fc41

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