Module

cache.query_index

Query Index - Base class for queryable indexes.

Provides O(1) lookups for common page queries by pre-computing indexes at build time. Similar to TaxonomyIndex but generalized for any page attribute.

Architecture:

  • Build indexes once during build phase (O(n) cost)
  • Persist to disk for incremental builds
  • Template access is O(1) hash lookup
  • Incrementally update only changed pages

Example:

# Built-in indexes
site.indexes.section.get('blog')        # O(1) - all blog posts
site.indexes.author.get('Jane Smith')   # O(1) - posts by Jane

# Custom indexes
site.indexes.status.get('published')    # O(1) - published posts

Classes

IndexEntry dataclass
A single entry in a query index. Represents one index key (e.g., 'blog' section, 'Jane Smith' auth…
6

A single entry in a query index.

Represents one index key (e.g., 'blog' section, 'Jane Smith' author) and all pages that match that key.

Implements the Cacheable protocol for type-safe serialization.

Inherits from Cacheable

Attributes

Name Type Description
key str

Index key (e.g., 'blog', 'Jane Smith', '2024')

page_paths list[str]

List of page source paths (strings, not Page objects)

metadata dict[str, Any]

Extra data for display (e.g., section title, author email)

updated_at str

ISO timestamp of last update

content_hash str

Hash of page_paths for change detection

Methods 4

to_cache_dict
Serialize to cache-friendly dictionary (Cacheable protocol).
0 dict[str, Any]
def to_cache_dict(self) -> dict[str, Any]

Serialize to cache-friendly dictionary (Cacheable protocol).

Returns

dict[str, Any]

from_cache_dict classmethod
Deserialize from cache dictionary (Cacheable protocol).
1 IndexEntry
def from_cache_dict(cls, data: dict[str, Any]) -> IndexEntry

Deserialize from cache dictionary (Cacheable protocol).

Parameters 1
data dict[str, Any]
Returns

IndexEntry

to_dict
Alias for to_cache_dict (backward compatibility).
0 dict[str, Any]
def to_dict(self) -> dict[str, Any]

Alias for to_cache_dict (backward compatibility).

Returns

dict[str, Any]

from_dict staticmethod
Alias for from_cache_dict (backward compatibility).
1 IndexEntry
def from_dict(data: dict[str, Any]) -> IndexEntry

Alias for from_cache_dict (backward compatibility).

Parameters 1
data dict[str, Any]
Returns

IndexEntry

Internal Methods 2
__post_init__
Compute content hash if not provided.
0 None
def __post_init__(self) -> None

Compute content hash if not provided.

_compute_hash
Compute hash of page_paths for change detection.
0 str
def _compute_hash(self) -> str

Compute hash of page_paths for change detection.

Returns

str

QueryIndex abstract
Base class for queryable indexes. Subclasses define: - What to index (e.g., by_section, by_author,…
15

Base class for queryable indexes.

Subclasses define:

  • What to index (e.g., by_section, by_author, by_tag)
  • How to extract keys from pages
  • Optionally: custom serialization logic

The base class handles:

  • Index storage and persistence
  • Incremental updates
  • Change detection
  • O(1) lookups
Inherits from ABC

Methods 10

extract_keys
Extract index keys from a page. Returns list of (key, metadata) tuples. Can re…
1 list[tuple[str, dic…
def extract_keys(self, page: Page) -> list[tuple[str, dict[str, Any]]]

Extract index keys from a page.

Returns list of (key, metadata) tuples. Can return multiple keys for multi-valued indexes (e.g., multi-author papers, multiple tags).

Parameters 1
page Page

Page to extract keys from

Returns

list[tuple[str, dict[str, Any]]]

List of (key, metadata) tuples

update_page
Update index for a single page. Handles: - Removing page from old keys - Addin…
2 set[str]
def update_page(self, page: Page, build_cache: BuildCache) -> set[str]

Update index for a single page.

Handles:

  • Removing page from old keys
  • Adding page to new keys
  • Tracking affected keys for incremental regeneration
Parameters 2
page Page

Page to update

build_cache BuildCache

Build cache for dependency tracking

Returns

set[str]

Set of affected index keys (need regeneration)

remove_page
Remove page from all index entries.
1 set[str]
def remove_page(self, page_path: str) -> set[str]

Remove page from all index entries.

Parameters 1
page_path str

Path to page source file

Returns

set[str]

Set of affected keys

get
Get page paths for index key (O(1) lookup).
1 list[str]
def get(self, key: str) -> list[str]

Get page paths for index key (O(1) lookup).

Parameters 1
key str

Index key

Returns

list[str]

List of page paths (copy, safe to modify)

keys
Get all index keys.
0 list[str]
def keys(self) -> list[str]

Get all index keys.

Returns

list[str]

has_changed
Check if index entry changed (for skip optimization). Compares page_paths as s…
2 bool
def has_changed(self, key: str, page_paths: list[str]) -> bool

Check if index entry changed (for skip optimization).

Compares page_paths as sets (order doesn't matter for most use cases).

Parameters 2
key str

Index key

page_paths list[str]

New list of page paths

Returns

bool

True if entry changed and needs regeneration

get_metadata
Get metadata for index key.
1 dict[str, Any]
def get_metadata(self, key: str) -> dict[str, Any]

Get metadata for index key.

Parameters 1
key str

Index key

Returns

dict[str, Any]

Metadata dict (empty if key not found)

save_to_disk
Persist index to disk.
0 None
def save_to_disk(self) -> None

Persist index to disk.

clear
Clear all index data.
0 None
def clear(self) -> None

Clear all index data.

stats
Get index statistics.
0 dict[str, Any]
def stats(self) -> dict[str, Any]

Get index statistics.

Returns

dict[str, Any]

Dictionary with index stats

Internal Methods 5
__init__
Initialize query index.
2 None
def __init__(self, name: str, cache_path: Path)

Initialize query index.

Parameters 2
name str

Index name (e.g., 'section', 'author')

cache_path Path

Path to cache file (e.g., .bengal/indexes/section_index.json)

_load_from_disk
Load index from disk.
0 None
def _load_from_disk(self) -> None

Load index from disk.

_add_page_to_key
Add page to index key.
3 None
def _add_page_to_key(self, key: str, page_path: str, metadata: dict[str, Any]) -> None

Add page to index key.

Parameters 3
key str

Index key

page_path str

Path to page source file

metadata dict[str, Any]

Metadata to store with this entry

_remove_page_from_key
Remove page from index key.
2 None
def _remove_page_from_key(self, key: str, page_path: str) -> None

Remove page from index key.

Parameters 2
key str

Index key

page_path str

Path to page source file

__repr__
String representation.
0 str
def __repr__(self) -> str

String representation.

Returns

str