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.0.tar.gz (16.0 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.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: xapian_model-0.4.0.tar.gz
  • Upload date:
  • Size: 16.0 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.0.tar.gz
Algorithm Hash digest
SHA256 c1af4e2ac6e7adba4bf1285a52551ff17cb78cb125f93aca87f00876b3dc80a1
MD5 02d05422bda35add6ff2d89c6ea368b5
BLAKE2b-256 7956b9a699d5967acd655be7c050869f5ac08c82f9d083ec2ae02b55bf4b7b0f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: xapian_model-0.4.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b3aefd7735718ce95997faee5899100af8591935848838f8f87ecc79120bac7f
MD5 d2788d11aef1ad98c4715463b8d849d2
BLAKE2b-256 8ac3a7e50ad1ceb963f155b8e6ee49c55f9dfb717c71716fa6dd8df98e767a6e

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