Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datetime not updating and not updating frequently #420

Open
TyroneTang opened this issue Feb 24, 2024 · 0 comments
Open

Datetime not updating and not updating frequently #420

TyroneTang opened this issue Feb 24, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@TyroneTang
Copy link

TyroneTang commented Feb 24, 2024

Hi all,

not sure if this is my pydantic model configuration problem, but i found some datetime fields not updating correctly and consistently (inside Mongodb Compass)

Bug

2 Problems:

  1. When using Pydantic V2.5 having the @model_validator or @field_validator decorator in the respective model to handle datetime update, Mongodb engine does not update datetime fields with session.save() . I tried / experimented using this for multiple fields for other datatypes, i.e., string, and UUID, both update consistently into the database.

  2. Using <collection>.model_update() as recommended in the docs, does it correctly to update datetime fields. However the frequency of update is inconsistent.

Temporary fix
To overcome this (for the time being), i used <collection>.model_copy() to make a quick copy with session.save() . This now updates the document datetime field at the consistent rate.

Things to note:
I'm saving / updating documents in mongodb at the rate of 1 doc per sec and 3 doc per sec.

What i noticed after digging around is, inside the _BaseODMModel it does not capture the fields as __fields_modified__ and is_type_mutable returns as false. Not sure if that helps

Current Behavior

### Schema

from odmantic import Model, Field, bson
from odmantic.bson import BSON_TYPES_ENCODERS
from odmantic.config import ODMConfigDict
from pydantic import field_validator, UUID4, model_validator, BaseModel
from bson.binary import Binary
from datetime import datetime
from typing import Any
from uuid import uuid4
from typing_extensions import Self


class BookCollection(Model):
    id: UUID4 = Field(primary_field=True, default_factory=uuid4)
    book_id: UUID4
    borrorwer: str 

    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

    model_config = ODMConfigDict(
        collection="BOOK_COLLECTION",
    )

    @model_validator(mode="before") # type: ignore
    def update_field_updated_at(cls, input: dict) -> dict:
        input["updated_at"] = datetime.utcnow()

        return input

    # > This one works. (Above does not), Also did this using @field_validator, only book_id works, not for updated_at (datetime)
    # @model_validator(mode="before")
    # def validate_field_book_id(cls, input: dict) -> dict:
    #     input["book_id"] = uuid4()
    #     return input
@asynccontextmanager
async def get_mongodb() -> AsyncGenerator[MongoDB, None]:
    try:
        mongodb = MongoDB()
        # 01 Start session
        await mongodb.start_session()

        yield mongodb

    finally:
        # 02 gracefully end session
        await mongodb.end_session()




def func_update_id(new_id: string) -> None:
       async with get_mongodb() as mongodb:
              result = await mongodb.session.find_one(
                       BookCollection,
                       BookCollection.book_id == UUID("69e4ea5b-1751-4579-abb1-60c31e939c0f")
               )

               if result is None:
                        logger.error("Book Doc not found!")
                        return None

               else:
                       # Method 1
                       # Bug 1 > datetime does not save into mongodb, but returned model shows its updated.
                       result.model_update()
                       result.book_id = new_id
                       data = await mongodb.session.save(result)

                       # Method 2
                       # Bug 2 > datetime saves into mongodb, but not consistently.
                       result.model_update({"book_id": new_id})
                       data = await mongodb.session.save(result)
                   

                       # quick fix
                       result.book_id = new_id
                       data = await mongodb.session.save(result.model_copy())

### Expected behavior

To update `datetime` fields in mongodb engine at a consistent rate using pydantic decorators

### Environment

- ODMantic version: "^1.0.0"
- MongoDB version: [6.00](mongo:6.0) Docker
- Pydantic: ^2.5
- Mongodb Compass: 1.35
@TyroneTang TyroneTang added the bug Something isn't working label Feb 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant