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.3.2.tar.gz (11.8 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.3.2-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: xapian_model-0.3.2.tar.gz
  • Upload date:
  • Size: 11.8 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.3.2.tar.gz
Algorithm Hash digest
SHA256 ca6bc551fedd394c108675343aea45add8f777b99ec5529cdcbefb4a6fbd4fae
MD5 0da4f74c3ba399d2e50454faeae3f11a
BLAKE2b-256 871eaec296f9b4fc2b05c5816d62adc03d7aafaf6490d1bde66ae2041d2db2f7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: xapian_model-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 7.8 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.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bd6b229db0ba462494ee164eb9f2ac0dc90874aae744a81cf1db1971f2db73f9
MD5 3893815562686a8b2632ef8b7c8d1c4f
BLAKE2b-256 97ee1df999dc4d9253c0a3c8b56973d6b4a85f9529ac913a671ca6d9b1830f25

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