Skip to content

Add update method and unify id attribute across all backends#316

Merged
vik-rant merged 4 commits intodevfrom
feature/284-task-database-enhancements
Jan 5, 2026
Merged

Add update method and unify id attribute across all backends#316
vik-rant merged 4 commits intodevfrom
feature/284-task-database-enhancements

Conversation

@mazenelabd
Copy link
Contributor

Add Update Method and Unify ID Attribute Across All Backends

Summary

This PR adds the update method to all database backends and ensures consistent id attribute access across MongoDB, Redis, and Registry backends. This enables unified CRUD operations and eliminates the need for backend-specific ID handling in application code.

Changes

1. Added update Method to All Backends

Implemented update method across all ODM backends with both sync and async support:

  • MongoDB (mongo_odm.py): Added update() and update_sync() methods
  • Redis (redis_odm.py): Added update() and update_async() methods
  • Registry (registry_odm.py): Added update() method supporting both legacy update(id, obj) and new update(obj) signatures
  • Unified (unified_odm.py): Added update() and update_async() methods that route to the active backend
  • Abstract Base (mindtrace_odm.py): Added abstract update() method to the base class

Usage:

# Get a document
user = await db.get_async(user_id)

# Modify it
user.name = "Updated Name"
user.age = 31

# Update it
updated_user = await db.update_async(user)

2. Unified ID Attribute Access

Redis Backend

  • Added id property to MindtraceRedisDocument that mirrors the pk attribute
  • Implemented both getter and setter to ensure compatibility with Redis-OM deserialization
  • All Redis documents now expose id consistently, eliminating the need to check for pk or id

Implementation:

@property
def id(self) -> str | None:
    """Return the primary key as 'id' for consistency with MongoDB."""
    return getattr(self, "pk", None)

@id.setter
def id(self, value: str | None) -> None:
    """Set the primary key when 'id' is set."""
    object.__setattr__(self, "pk", value)

Registry Backend

  • Ensured id attribute is set on all returned documents
  • Since Registry deserializes documents (losing non-field attributes), id is restored during retrieval
  • Optimized to set id during insert() and update(), and restore it in get(), all(), and find()

Implementation:

  • insert(): Sets id on the document before storing
  • update(): Sets id on the document (both legacy and new style)
  • get(), all(), find(): Restore id from the registry key since deserialization loses it

3. Test Coverage

  • 100% coverage

Example Usage

Before (Backend-Specific ID Handling)

# Had to check for pk or id depending on backend
user_id = getattr(user, 'pk', None) or getattr(user, 'id', None)
user = await db.get_async(user_id)
user.name = "Updated"
# No unified update method

After (Unified Interface)

# Consistent id access
user = await db.get_async(user_id)
user.name = "Updated"
updated_user = await db.update_async(user)  # Works with all backends

Benefits

  1. Unified CRUD Operations: Complete CRUD support across all backends
  2. Consistent ID Access: No more checking for pk vs id - just use doc.id
  3. Better Developer Experience: Same API regardless of backend choice
  4. Type Safety: Clear method signatures and return types
  5. Full Test Coverage: Comprehensive test suite ensures reliability

Migration Guide

No migration needed - this is fully backward compatible. However, you can now:

  1. Use update() instead of manual save operations:

    # Old way (still works)
    user = await db.get_async(user_id)
    user.name = "Updated"
    await user.save()  # MongoDB
    user.save()  # Redis
    
    # New way (recommended)
    user = await db.get_async(user_id)
    user.name = "Updated"
    updated_user = await db.update_async(user)  # Works everywhere
  2. Use id attribute consistently:

    # Old way (still works)
    user_id = getattr(user, 'pk', None) or getattr(user, 'id', None)
    
    # New way (recommended)
    user_id = user.id  # Works with all backends

@mazenelabd mazenelabd requested a review from vik-rant December 18, 2025 14:44
@mazenelabd mazenelabd self-assigned this Dec 18, 2025
@mazenelabd mazenelabd assigned ghost and mazenelabd and unassigned mazenelabd and ghost Dec 18, 2025
@canelbirlik
Copy link
Contributor

Hi Mazen, I'll review the PR later but while we are at it can we take a look at this issue :
#271 (comment)

Essentially I think rather initializing beanie with a single doc, we pass in multiple docs at init.

@nanwang-mindtrace nanwang-mindtrace linked an issue Dec 19, 2025 that may be closed by this pull request
@mazenelabd
Copy link
Contributor Author

Hi Mazen, I'll review the PR later but while we are at it can we take a look at this issue : #271 (comment)

Essentially I think rather initializing beanie with a single doc, we pass in multiple docs at init.

Will make sure to support it in a different branch. Hopefully today.

@vik-rant vik-rant merged commit 1720312 into dev Jan 5, 2026
4 checks passed
@vik-rant vik-rant deleted the feature/284-task-database-enhancements branch January 5, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task] Database Enhancements

3 participants