Skip to main content

Python client library for the Xapiand search engine

Project description

Xapiand Python Client

Python client library for Xapiand, a RESTful search engine built on top of Xapian.

Features

  • Full coverage of Xapiand REST operations: search, get, post, put, patch, merge, delete, store, stats, and head.
  • Automatic serialization/deserialization with JSON and msgpack (preferred when available).
  • Django settings integration for seamless configuration in Django projects.
  • Attribute-style access on response objects (result.hits instead of result['hits']).
  • Custom HTTP methods (MERGE, STORE) supported via an extended requests.Session.

Requirements

Installation

pip install xapiand

With optional msgpack support (recommended for better performance):

pip install xapiand[msgpack]

For development (editable install):

git clone https://github.com/pber/xapiand.git
cd xapiand
pip install -e .[msgpack]

Quick Start

from xapiand import Xapiand

client = Xapiand(host="localhost", port=8880)

# Index a document
client.put("books", body={"title": "The Art of Search", "year": 2024}, id="book1")

# Retrieve a document
doc = client.get("books", id="book1")
print(doc.title)  # "The Art of Search"

# Search
results = client.search("books", query="search")
for hit in results.hits:
    print(hit.title)

# Delete a document
client.delete("books", id="book1")

A pre-configured module-level client singleton is also available:

from xapiand import client

results = client.search("myindex", query="hello world")
print(results.count)  # total count
print(results.total)  # estimated matches

Configuration

The client reads configuration from environment variables, with optional overrides from Django settings:

Environment Variable Django Setting Default Description
XAPIAND_HOST settings.XAPIAND_HOST 127.0.0.1 Server hostname
XAPIAND_PORT settings.XAPIAND_PORT 8880 Server port
XAPIAND_COMMIT settings.XAPIAND_COMMIT False Auto-commit write operations
XAPIAND_PREFIX settings.XAPIAND_PREFIX default URL prefix prepended to index paths

Django settings take precedence over environment variables when Django is available.

Client initialization

You can also pass configuration directly when creating a client:

client = Xapiand(
    host="192.168.1.100",
    port=8880,
    commit=True,          # auto-commit writes
    prefix="production",  # URL prefix for index paths
)

The host parameter accepts a host:port format ("192.168.1.100:9000"), in which case the port part overrides the port parameter.

API Reference

All API methods return DictObject instances, which are dictionaries with attribute-style access.

Search

results = client.search(
    "myindex",
    query="hello world",    # query string
    partial="hel",          # partial query for autocomplete
    terms="tag:python",     # term filters
    offset=0,               # starting offset
    limit=10,               # max results
    sort="date",            # sort field
    language="en",          # query language
    check_at_least=100,     # minimum documents to check
)

results.hits    # list of matching documents
results.count   # total count
results.total   # estimated matches

Search with a request body (uses POST internally):

results = client.search("myindex", body={
    "_query": {"title": "search engine"},
})

Count

results = client.count("myindex", query="hello")
print(results.count)

Get

doc = client.get("myindex", id="doc1")

# With a default value (returns it instead of raising on 404)
doc = client.get("myindex", id="doc1", default=None)

Create (POST)

# Server-assigned ID
result = client.post("myindex", body={"title": "New Document"})

Create or Replace (PUT)

result = client.put("myindex", body={"title": "My Document"}, id="doc1")

# Alias
result = client.index("myindex", body={"title": "My Document"}, id="doc1")

Partial Update (PATCH)

result = client.patch("myindex", id="doc1", body={"title": "Updated Title"})

Deep Merge (MERGE)

Uses Xapiand's custom MERGE HTTP method for deep-merging fields:

result = client.merge("myindex", id="doc1", body={"metadata": {"tags": ["new"]}})

Update

Chooses strategy based on content type:

# Partial merge (default)
client.update("myindex", id="doc1", body={"title": "Updated"})

# Full replacement when content_type is specified
client.update("myindex", id="doc1", body=data, content_type="application/json")

Delete

client.delete("myindex", id="doc1")

Store

Store binary content using Xapiand's custom STORE HTTP method:

client.store("myindex", id="doc1", body="/path/to/file.bin")

Head

Check if a document exists:

client.head("myindex", id="doc1")

Stats

stats = client.stats("myindex")

Common Parameters

Most methods accept these optional parameters:

Parameter Type Description
commit bool Commit changes immediately (write ops)
pretty bool Request pretty-printed response
volatile bool Bypass caches, read from disk
kwargs dict Additional arguments passed to requests

Error Handling

from xapiand import Xapiand, TransportError

client = Xapiand()

# NotFoundError on missing documents
try:
    doc = client.get("myindex", id="nonexistent")
except client.NotFoundError:
    print("Document not found")

# TransportError (requests.HTTPError) on other HTTP errors
try:
    client.search("myindex", query="test")
except TransportError as e:
    print(f"HTTP error: {e}")

When Django is installed, NotFoundError is a subclass of django.core.exceptions.ObjectDoesNotExist, making it compatible with Django's error handling patterns.

Utilities

xapiand.collections

Dict subclasses with attribute-style access:

from xapiand.collections import DictObject, OrderedDictObject

obj = DictObject(name="test", value=42)
obj.name      # "test"
obj["value"]  # 42

xapiand.constants

Predefined Xapian term constants for configuring index schema accuracy:

from xapiand.constants import (
    # Date accuracy
    HOUR_TERM, DAY_TERM, MONTH_TERM, YEAR_TERM,
    DAY_TO_YEAR_ACCURACY,     # [day, month, year]
    HOUR_TO_YEAR_ACCURACY,    # [hour, day, month, year]

    # Geospatial accuracy (HTM levels)
    LEVEL_0_TERM,             # ~10,000 km
    LEVEL_10_TERM,            # ~10 km
    LEVEL_20_TERM,            # ~10 m
    STATE_TO_BLOCK_ACCURACY,  # [level_5, level_10, level_15]

    # Numeric accuracy
    TENS_TO_TEN_THOUSANDS_ACCURACY,
    HUDREDS_TO_MILLIONS_ACCURACY,
)

xapiand.utils

Xapian-compatible binary serialization for lengths, strings, and characters:

from xapiand.utils import serialise_length, unserialise_length

encoded = serialise_length(42)
length, remaining = unserialise_length(encoded)
assert length == 42

License

MIT License - Copyright (c) 2015-2026 Dubalu LLC

See LICENSE for details.

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

pyxapiand-1.0.0.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

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

pyxapiand-1.0.0-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file pyxapiand-1.0.0.tar.gz.

File metadata

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

File hashes

Hashes for pyxapiand-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5ed7c1a871805dc305f862c7cf8885d4188e1856aa8f8606b58c1635785aec8c
MD5 b05a84c6472d85cf76c395b1aeff2839
BLAKE2b-256 b16355fef66e56cd9a4243a63308c4b1bcabdaaab5c0624b1d19a2e4400c83be

See more details on using hashes here.

File details

Details for the file pyxapiand-1.0.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for pyxapiand-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 91bb2f551fc65f0369acf9282e77c22d71730dc32be93c1267c778d0a7412b61
MD5 bcf6538aea671118ae02b99ef37c5ca6
BLAKE2b-256 f403851bc33ef40ae5c0b387f8d13ee6711043b27f00fc3ebdc54cce0f1002d6

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