Skip to main content

Key/value store abstraction with hierarchical keys, pattern matching, and metadata support

Project description

DataKnobs KV Package

A powerful key/value store abstraction with hierarchical keys, pattern matching, and rich metadata support, built on top of the dataknobs-data package.

Overview

The dataknobs-kv package provides a simple yet powerful interface for managing key/value pairs across multiple storage backends. It features hierarchical key structures, advanced pattern matching, metadata management, and seamless integration with various storage technologies through the dataknobs-data abstraction layer.

Features

  • Hierarchical Keys: Dot-notation key paths for organized data structure
  • Pattern Matching: Powerful glob-style patterns for key operations
  • Rich Metadata: Associate custom metadata with every key/value pair
  • Multiple Backends: Memory, File, PostgreSQL, Elasticsearch, S3, and more
  • TTL Support: Automatic expiration for time-sensitive data
  • Atomic Operations: Compare-and-swap, increment, append operations
  • Namespace Isolation: Multi-tenant support with isolated namespaces
  • Type Safety: Strong typing with automatic serialization/deserialization

Installation

# Basic installation
pip install dataknobs-kv

# With caching support
pip install dataknobs-kv[cache]

# With all features
pip install dataknobs-kv[all]

Quick Start

from dataknobs_kv import KVStore

# Create a store with memory backend
store = KVStore(backend="memory")

# Basic operations
await store.set("app.name", "MyApplication")
await store.set("app.version", "1.0.0")
await store.set("app.config.debug", True)

# Get values
name = await store.get("app.name")
debug = await store.get("app.config.debug")

# Pattern matching
app_keys = await store.keys("app.*")
all_config = await store.get_pattern("app.config.*")

# Delete keys
await store.delete("app.config.debug")
await store.delete_pattern("app.temp.*")

Hierarchical Key Structure

# Organize data with dot-notation paths
await store.set("users.123.name", "John Doe")
await store.set("users.123.email", "john@example.com")
await store.set("users.123.settings.theme", "dark")
await store.set("users.123.settings.notifications", True)

# Get all user data
user_data = await store.get_pattern("users.123.*")

# Get all user settings
user_settings = await store.get_pattern("users.123.settings.*")

# Delete entire user
await store.delete_pattern("users.123.**")

Pattern Matching

# Wildcards
await store.keys("users.*.name")        # All user names
await store.keys("*.config.*")          # All config at any level
await store.keys("logs.2024-*")         # All 2024 logs

# Recursive wildcards
await store.keys("app.**")              # Everything under app
await store.keys("**.error")            # All error keys at any level

# Single character and sets
await store.keys("user.?.name")         # user.1.name, user.a.name, etc.
await store.keys("log.[0-9].txt")       # log.0.txt through log.9.txt

# Alternatives
await store.keys("env.{dev,prod}.config") # dev or prod config

Metadata Management

# Set with metadata
await store.set(
    "document.report.pdf",
    document_bytes,
    metadata={
        "content_type": "application/pdf",
        "author": "John Doe",
        "created": "2024-01-15",
        "tags": ["quarterly", "finance"],
        "ttl": 86400  # Expire in 24 hours
    }
)

# Get metadata
metadata = await store.get_metadata("document.report.pdf")
print(f"Author: {metadata['author']}")
print(f"Tags: {metadata['tags']}")

# Update metadata
await store.set_metadata("document.report.pdf", {
    "reviewed": True,
    "reviewer": "Jane Smith"
})

TTL and Expiration

# Set with TTL (time to live)
await store.set("session.abc123", session_data, ttl=3600)  # 1 hour
await store.set("cache.results", results, ttl=300)         # 5 minutes

# Check if key exists (returns False if expired)
if await store.exists("session.abc123"):
    data = await store.get("session.abc123")

# Manual cleanup of expired keys
expired_count = await store.cleanup_expired()
print(f"Removed {expired_count} expired keys")

# Automatic cleanup (runs in background)
store = KVStore(backend="memory", auto_cleanup=True, cleanup_interval=60)

Atomic Operations

# Compare and swap (CAS)
success = await store.compare_and_swap(
    "version",
    old_value="1.0.0",
    new_value="1.1.0"
)

# Increment/decrement counters
views = await store.increment("stats.page_views")
remaining = await store.increment("inventory.item_123", delta=-1)

# Append to strings
await store.append("logs.access", "\n2024-01-15 10:30 User login")
await store.append("notes", ", Remember to update docs")

Batch Operations

# Set multiple values
await store.set_many({
    "config.host": "localhost",
    "config.port": 8080,
    "config.ssl": True,
    "config.timeout": 30
})

# Get multiple values
values = await store.get_many([
    "config.host",
    "config.port",
    "config.ssl"
])

# Delete multiple keys
deleted = await store.delete_many([
    "temp.file1",
    "temp.file2",
    "cache.old"
])

Namespace Isolation

# Create isolated namespaces
user_store = KVStore(backend="postgres", namespace="user_data")
system_store = KVStore(backend="postgres", namespace="system")
cache_store = KVStore(backend="memory", namespace="cache")

# Same keys, different namespaces
await user_store.set("settings", {"theme": "dark"})
await system_store.set("settings", {"debug": True})

# Values are isolated
user_settings = await user_store.get("settings")   # {"theme": "dark"}
system_settings = await system_store.get("settings") # {"debug": True}

Backend Configuration

Memory Backend

store = KVStore(backend="memory")

File Backend

store = KVStore(backend="file", config={
    "path": "/data/kv_store.json",
    "format": "json",
    "compression": "gzip"
})

PostgreSQL Backend

store = KVStore(backend="postgres", config={
    "host": "localhost",
    "database": "myapp",
    "table": "kv_store",
    "user": "dbuser",
    "password": "dbpass"
})

Redis Backend

store = KVStore(backend="redis", config={
    "host": "localhost",
    "port": 6379,
    "db": 0,
    "password": "optional"
})

S3 Backend

store = KVStore(backend="s3", config={
    "bucket": "my-kv-store",
    "prefix": "data/",
    "region": "us-west-2"
})

Advanced Usage

Custom Serialization

import pickle

# Custom serializer for complex objects
class CustomStore(KVStore):
    def serialize(self, value):
        if isinstance(value, MyComplexClass):
            return pickle.dumps(value)
        return super().serialize(value)
    
    def deserialize(self, data, value_type):
        if value_type == "custom":
            return pickle.loads(data)
        return super().deserialize(data, value_type)

Caching Layer

# Add caching for performance
store = KVStore(
    backend="postgres",
    cache="memory",
    cache_ttl=60,  # Cache for 60 seconds
    cache_size=1000  # Max 1000 items in cache
)

Migration Between Backends

from dataknobs_kv import migrate_store

# Migrate from file to PostgreSQL
source = KVStore(backend="file", config={"path": "data.json"})
target = KVStore(backend="postgres", config=postgres_config)

await migrate_store(source, target, batch_size=100)

Development

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=dataknobs_kv

# Type checking
mypy src/dataknobs_kv

# Linting
ruff check src/dataknobs_kv

# Format code
black src/dataknobs_kv

Architecture

The package is built on top of dataknobs-data, providing:

  • Keys: Hierarchical path management with validation
  • Values: Type-safe serialization/deserialization
  • Patterns: Advanced pattern matching engine
  • Metadata: Rich metadata with system and user fields
  • Namespaces: Isolation for multi-tenant applications
  • Backends: Leverages dataknobs-data storage backends

Performance

  • Optimized pattern matching with compiled regex
  • Efficient batch operations
  • Optional caching layer
  • Connection pooling for database backends
  • Async/await support for concurrent operations

Contributing

Contributions are welcome! Please see our Contributing Guide for details.

License

This project is licensed under the MIT License - see the LICENSE file 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

dataknobs_kv-0.1.0.tar.gz (10.1 kB view details)

Uploaded Source

Built Distribution

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

dataknobs_kv-0.1.0-py3-none-any.whl (4.2 kB view details)

Uploaded Python 3

File details

Details for the file dataknobs_kv-0.1.0.tar.gz.

File metadata

  • Download URL: dataknobs_kv-0.1.0.tar.gz
  • Upload date:
  • Size: 10.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.12

File hashes

Hashes for dataknobs_kv-0.1.0.tar.gz
Algorithm Hash digest
SHA256 252f4f198e370be47f58b6cfff043c12605d5a89e94bb87f7f941c0d346216e3
MD5 e32d6183fa2be912a258c061c409184a
BLAKE2b-256 3d4f403510416ea8a57c935cc58585bc6b731b577573c6d96b84e81479cb1111

See more details on using hashes here.

File details

Details for the file dataknobs_kv-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for dataknobs_kv-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 897d86c8fb6dbc4b3b085776b2363a0d4d7de220203cbb6d0449056f8c0fb02d
MD5 fd66642c8cdc21e03013adc4c5998f2d
BLAKE2b-256 e89a7e58c5d713cdeea72c3965e20523eebbaab6e0f957e3f66d370984fc6aab

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