API Reference
index

dbzero.index()

Creates and returns a new Index object. An index is a persistent, ordered data structure, similar to a B-Tree, that allows you to efficiently query and sort your dbzero-managed objects. You can think of it as a dictionary where the keys are always sorted, enabling fast range scans and ordered iteration.

Indexes are incredibly useful for maintaining ordered collections, like a list of tasks sorted by priority or a log of events sorted by timestamp.

Returns

An empty Index object.

Example

# Create a new index and assign it to an object's attribute
tasks_by_priority = db0.index()
 
# You can also assign it directly as a member of a memoized class
class Project:
    def __init__(self, name):
        self.name = name
        self.tasks = db0.index()

The Index Object

The Index object returned by dbzero.index() provides methods to add, remove, and query objects based on their associated keys. All modifications to an Index are transactional and will be reverted if the enclosing dbzero.atomic() context is cancelled or raises an exception.

index.add(key, value)

Associates a value (which must be a dbzero-managed object) with a sortable key. The type of the key determines the sorting order. Supported key types include numbers (int, float), datetime, date, and None.

  • key: The sortable key. Can be a number, datetime, date, or None.
  • value: The dbzero object to associate with the key.
💡

A single object can be added to an index multiple times with different keys.

Example

import datetime
 
tasks_index = db0.index()
high_priority_task = Task("Deploy to production")
low_priority_task = Task("Update documentation")
 
# Add tasks with a numeric priority key
tasks_index.add(1, high_priority_task)
tasks_index.add(10, low_priority_task)
 
# The key can also be a datetime or None
tasks_index.add(datetime.datetime.now(), Task("Urgent bug fix"))
tasks_index.add(None, Task("TBD task"))
 
assert len(tasks_index) == 4

index.remove(key, value)

Removes a specific key-value pair from the index. To successfully remove an entry, you must provide both the exact key and the object instance.

  • key: The key of the entry to remove.
  • value: The object instance of the entry to remove.

Example

tasks_index = db0.index()
task_to_remove = Task("Old task")
tasks_index.add(99, task_to_remove)
 
# To remove the task, you need both its key and the object itself
tasks_index.remove(99, task_to_remove)
 
assert len(tasks_index) == 0

index.select(min_key=None, max_key=None, *, null_first=False)

Returns an iterable containing all objects from the index whose keys fall within the [min_key, max_key] range. The range is inclusive.

  • min_key (object, optional): The minimum key for the range. If None, the range is unbounded on the lower end. Defaults to None.
  • max_key (object, optional): The maximum key for the range. If None, the range is unbounded on the upper end. Defaults to None.
  • null_first (bool, optional): A flag that affects how None keys are positioned for querying. When True, None keys are treated as being at the very beginning of the index, before any other value. Defaults to False.
💡

Calling index.select() with no arguments returns an iterable of all objects in the index.

Example

import datetime
 
events = db0.index()
now = datetime.datetime.now()
 
events.add(now - datetime.timedelta(days=2), Event("Event 1"))
events.add(now - datetime.timedelta(days=1), Event("Event 2"))
events.add(now, Event("Event 3"))
events.add(now + datetime.timedelta(days=1), Event("Event 4"))
events.add(None, Event("Unscheduled Event"))
 
# Get events from the last day (inclusive)
recent_events = events.select(now - datetime.timedelta(days=1), now)
assert len(list(recent_events)) == 2
 
# Get all future events
future_events = events.select(min_key=now)
assert len(list(future_events)) == 2
 
# Get all events including the unscheduled one
all_events = events.select(null_first=True)
assert len(list(all_events)) == 5

index.sort(iterable, *, desc=False, null_first=False)

Sorts a given iterable of objects based on the keys they have in this index. This powerful method allows you to combine tag-based searches or other queries with custom sorting logic.

  • iterable: An iterable of dbzero objects that you want to sort (e.g., the result of dbzero.find()).
  • desc (bool, optional): If True, sorts the results in descending order. Defaults to False.
  • null_first (bool, optional): When True, items with a None key appear first in ascending sorts and last in descending sorts. When False, None-keyed items appear last in ascending sorts and first in descending sorts. The default behavior places Nones last in ascending order and first in descending order.

Example: Basic Sorting

# Create some tagged tasks with different priorities
tasks = db0.index()
for i in range(5):
    task = Task(f"Task {i}")
    db0.tags(task).add("project-alpha")
    tasks.add(5 - i, task) # Priority key: 5, 4, 3, 2, 1
 
# Find all tasks for "project-alpha" and sort them by priority
all_alpha_tasks = db0.find("project-alpha")
sorted_tasks = tasks.sort(all_alpha_tasks)
 
# Result will be ordered by priority: Task 4, Task 3, ...
priorities = [t.priority for t in sorted_tasks]
assert priorities == [1, 2, 3, 4, 5]

Example: Multi-level Sorting

You can chain sort() calls to sort by multiple criteria. The last sort() call determines the primary sort order.

# Tasks have a priority and a due date
priority_index = db0.index()
date_index = db0.index()
 
# ... add tasks to both indexes ...
 
# Find all tasks
all_tasks = db0.find(Task)
 
# Sort by date first, then by priority
# The final order will be primarily by priority, with date as a tie-breaker.
sorted_by_priority_then_date = priority_index.sort(date_index.sort(all_tasks))