Python client for ekoDB - a high-performance document database
Project description
ekoDB Python Client
High-performance Python client for ekoDB, built with Rust for speed and safety.
This package wraps the ekodb_client Rust library using PyO3 to provide a
native Python interface.
Features
- ✅ Fast: Built with Rust, leveraging the same client library as the Rust SDK
- ✅ Type-safe: Strong typing with Python type hints
- ✅ Async/await: Full async support using Python's asyncio
- ✅ Easy to use: Pythonic API that feels natural
- ✅ Complete: All ekoDB features supported
- ✅ Query Builder - Fluent API for complex queries with operators, sorting, and pagination
- ✅ Search - Full-text search, fuzzy search, and field-specific search with scoring
- ✅ Schema Management - Define and enforce data schemas with validation
- ✅ Join Operations - Single and multi-collection joins with queries
- ✅ Rate limiting with automatic retry (429, 503, network errors)
- ✅ Rate limit tracking (
X-RateLimit-*headers) - ✅ Configurable retry behavior
- ✅ Retry-After header support
Installation
pip install ekodb
Or install from source:
cd ekodb-py
pip install maturin
maturin develop
Quick Start
import asyncio
from ekodb_client import Client, RateLimitError
async def main():
# Create client with configuration
client = Client.new(
"http://localhost:8080",
"your-api-key",
should_retry=True, # Enable automatic retries (default: True)
max_retries=3, # Maximum retry attempts (default: 3)
timeout_secs=30 # Request timeout in seconds (default: 30)
)
try:
# Insert a document
record = await client.insert("users", {
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"active": True
})
print(f"Inserted: {record['id']}")
# Find by ID
user = await client.find_by_id("users", record["id"])
print(f"Found: {user}")
# Find with query
results = await client.find("users", limit=10)
print(f"Found {len(results)} users")
# Update
updated = await client.update("users", record["id"], {
"age": 31
})
print(f"Updated: {updated}")
# Delete
await client.delete("users", record["id"])
print("Deleted")
except RateLimitError as e:
print(f"Rate limited! Retry after {e.retry_after_secs} seconds")
asyncio.run(main())
Usage Examples
Query Builder
from ekodb_client import Client, QueryBuilder
async def main():
client = Client.new("http://localhost:8080", "your-api-key")
# Simple query with operators
query = QueryBuilder() \
.eq("status", "active") \
.gte("age", 18) \
.lt("age", 65) \
.limit(10) \
.build()
results = await client.find("users", query)
# Complex query with sorting and pagination
query = QueryBuilder() \
.in_array("status", ["active", "pending"]) \
.contains("email", "@example.com") \
.sort_desc("created_at") \
.skip(20) \
.limit(10) \
.build()
results = await client.find("users", query)
Search Operations
# Basic text search
search_query = {
"query": "programming",
"min_score": 0.1,
"limit": 10
}
results = await client.search("articles", search_query)
for result in results["results"]:
print(f"Score: {result['score']:.4f} - {result['record']['title']}")
# Search with field weights
search_query = {
"query": "rust database",
"fields": ["title", "description"],
"weights": {"title": 2.0},
"limit": 5
}
results = await client.search("articles", search_query)
Schema Management
# Create a collection with schema
schema = {
"fields": {
"name": {
"field_type": "String",
"required": True,
"regex": "^[a-zA-Z ]+$"
},
"email": {
"field_type": "String",
"required": True,
"unique": True
},
"age": {
"field_type": "Integer",
"min": 0,
"max": 150
}
}
}
await client.create_collection("users", schema)
# Get collection schema
schema = await client.get_schema("users")
Join Operations
# Single collection join
query = {
"join": {
"collections": ["departments"],
"local_field": "department_id",
"foreign_field": "id",
"as_field": "department"
},
"limit": 10
}
results = await client.find("users", query)
# Multi-collection join
query = {
"join": [
{
"collections": ["departments"],
"local_field": "department_id",
"foreign_field": "id",
"as_field": "department"
},
{
"collections": ["profiles"],
"local_field": "id",
"foreign_field": "id",
"as_field": "profile"
}
],
"limit": 10
}
results = await client.find("users", query)
API Reference
Client
Client.new(base_url: str, api_key: str, should_retry: bool = True, max_retries: int = 3, timeout_secs: int = 30) -> Client
Create a new ekoDB client.
Parameters:
base_url: The base URL of the ekoDB serverapi_key: Your API keyshould_retry: Enable automatic retries (default: True)max_retries: Maximum number of retry attempts (default: 3)timeout_secs: Request timeout in seconds (default: 30)
Returns:
- A new
Clientinstance
RateLimitInfo
Rate limit information is automatically tracked and logged by the client. The
client will automatically retry on rate limit errors using the server's
Retry-After header.
Properties
limit: int- Maximum requests allowed per windowremaining: int- Requests remaining in current windowreset: int- Unix timestamp when the rate limit resets
Methods
is_near_limit() -> bool- Check if approaching rate limit (<10% remaining)is_exceeded() -> bool- Check if the rate limit has been exceededremaining_percentage() -> float- Get the percentage of requests remaining
RateLimitError
Exception raised when rate limit is exceeded (if retries are disabled or exhausted).
Properties
retry_after_secs: int- Number of seconds to wait before retrying
await client.insert(collection: str, record: dict) -> dict
Insert a document into a collection.
Parameters:
collection: The collection namerecord: A dictionary representing the document
Returns:
- The inserted document with ID
await client.find_by_id(collection: str, id: str) -> dict
Find a document by ID.
Parameters:
collection: The collection nameid: The document ID
Returns:
- The found document
await client.find(collection: str, limit: Optional[int] = None) -> List[dict]
Find documents in a collection.
Parameters:
collection: The collection namelimit: Optional limit on number of results
Returns:
- List of matching documents
await client.update(collection: str, id: str, updates: dict) -> dict
Update a document.
Parameters:
collection: The collection nameid: The document IDupdates: Dictionary of fields to update
Returns:
- The updated document
await client.delete(collection: str, id: str) -> None
Delete a document.
Parameters:
collection: The collection nameid: The document ID
await client.list_collections() -> List[str]
List all collections.
Returns:
- List of collection names
await client.delete_collection(collection: str) -> None
Delete a collection.
Parameters:
collection: The collection name to delete
await client.search(collection: str, query: dict) -> dict
Perform full-text search on a collection.
Parameters:
collection: The collection namequery: Search query dictionary with fields likequery,fields,weights,min_score,limit
Returns:
- Search results with scores and matched records
await client.create_collection(collection: str, schema: dict) -> None
Create a collection with a schema.
Parameters:
collection: The collection nameschema: Schema definition dictionary
await client.get_schema(collection: str) -> dict
Get the schema for a collection.
Parameters:
collection: The collection name
Returns:
- Schema definition dictionary
await client.get_collection(collection: str) -> dict
Get collection metadata including schema.
Parameters:
collection: The collection name
Returns:
- Collection metadata dictionary
Examples
See the examples directory for complete working examples:
client_simple_crud.py- Basic CRUD operationsclient_query_builder.py- Complex queries with QueryBuilderclient_search.py- Full-text search operationsclient_schema.py- Schema managementclient_joins.py- Join operationsclient_batch_operations.py- Batch operationsclient_kv_operations.py- Key-value operations- And more...
Development
Building
# Install maturin
pip install maturin
# Build and install in development mode
maturin develop
# Build release wheel
maturin build --release
Testing
# Run Python tests
pytest
# Run with coverage
pytest --cov=ekodb
License
MIT OR Apache-2.0
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ekodb_client-0.4.0.tar.gz.
File metadata
- Download URL: ekodb_client-0.4.0.tar.gz
- Upload date:
- Size: 78.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ada1854e73d26e5a62f5b3a3212eeb71fa2651aaec9baf334f4aac9eb2d20b9
|
|
| MD5 |
21b18931c8a23f3b8edc8d053d378146
|
|
| BLAKE2b-256 |
32ac44e03ba67f8b2634aad5800f4420d65400113ec68e1f759fb382996af9f7
|
File details
Details for the file ekodb_client-0.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: ekodb_client-0.4.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 4.0 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4c22dbf7b6b3ca723ab44ab942eb906057effaa6e55eeaf78fb9d7dfc288f70
|
|
| MD5 |
535e7ec473be870b815335a0fd8487cc
|
|
| BLAKE2b-256 |
f7e6115a36c706aa29df40926c79c10b46b3743eee4e976a5f8d3bd2597e7c60
|
File details
Details for the file ekodb_client-0.4.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: ekodb_client-0.4.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e31cbc51ad11eabf6790ef3b32746e3454e0b96deafc589f45541998a33ff66
|
|
| MD5 |
b634fa2a88da4d26fbbfee7133e51985
|
|
| BLAKE2b-256 |
63a35c92a9d7af90c7a078ae4d876b4dcb2b92c2f3500d02194ddee6ad609c75
|