OxiDB's query engine supports rich filtering with comparison operators, logical combinators, and efficient index utilization. Queries use a JSON-based syntax inspired by MongoDB.

Comparison Operators

from oxidb import OxiDbClient
db = OxiDbClient("127.0.0.1", 4444)

# Exact match (implicit $eq)
db.find("users", {"status": "active"})

# Explicit $eq
db.find("users", {"age": {"$eq": 25}})

# Greater than / less than
db.find("users", {"age": {"$gt": 18}})
db.find("users", {"age": {"$gte": 21}})
db.find("users", {"age": {"$lt": 65}})
db.find("users", {"age": {"$lte": 30}})

# Not equal
db.find("users", {"role": {"$ne": "guest"}})

# In a set of values
db.find("users", {"role": {"$in": ["admin", "moderator"]}})

# Field exists
db.find("users", {"email": {"$exists": True}})

Logical Operators

Combine conditions with $and and $or:

# AND — find active users over 21
db.find("users", {
    "$and": [
        {"status": "active"},
        {"age": {"$gte": 21}}
    ]
})

# OR — find admins or moderators
db.find("users", {
    "$or": [
        {"role": "admin"},
        {"role": "moderator"}
    ]
})

# Combined — active users who are admin OR over 30
db.find("users", {
    "$and": [
        {"status": "active"},
        {"$or": [
            {"role": "admin"},
            {"age": {"$gt": 30}}
        ]}
    ]
})

Sorting

Sort results by one or more fields. Use 1 for ascending and -1 for descending:

# Sort by age ascending
db.find("users", {}, sort={"age": 1})

# Sort by created_at descending (newest first)
db.find("posts", {"published": True}, sort={"created_at": -1})

# Multi-field sort
db.find("products", {}, sort={"category": 1, "price": -1})
When an index exists on the sort field, OxiDB uses index-backed sort — iterating the BTreeMap directly in O(limit) instead of sorting all results in O(n log n).

Pagination

Use skip and limit for efficient pagination:

PAGE_SIZE = 20

# Page 1
page1 = db.find("products", {}, sort={"name": 1}, skip=0, limit=PAGE_SIZE)

# Page 2
page2 = db.find("products", {}, sort={"name": 1}, skip=20, limit=PAGE_SIZE)

# Get total count for pagination controls
total = db.count("products", {})
total_pages = (total + PAGE_SIZE - 1) // PAGE_SIZE

Date Handling

OxiDB automatically detects and indexes dates from ISO 8601, RFC 3339, and YYYY-MM-DD strings. Dates are stored as epoch milliseconds internally, enabling proper date range queries:

# Find posts from March 2026
db.find("posts", {
    "$and": [
        {"created_at": {"$gte": "2026-03-01"}},
        {"created_at": {"$lt": "2026-04-01"}}
    ]
})

Cross-Type Ordering

OxiDB enforces a consistent ordering across types: Null < Bool < Number < DateTime < String. This ensures predictable sorting even with mixed-type fields.