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

Dates get casted to datetimes on retrieved objects, causing parsing errors during updates #1913

Closed
lunalucadou opened this issue Sep 12, 2024 · 2 comments · Fixed by #1914
Closed
Labels
Category: Bug Something isn't right Priority: High

Comments

@lunalucadou
Copy link

lunalucadou commented Sep 12, 2024

I have the following document class, along with a helper method that adapts objects from our existing SQL database:

class EsIdCard(InnerDoc):
    id: int
    card_number: str
    expiration_date: date

    @staticmethod
    def from_sql_id_card(sql_id_card: SqlIdCard) -> "EsIdCard":
        return EsIdCard(
            id=sql_id_card.id,
            card_number=sql_id_card.card_number,
            expiration_date=sql_id_card.expiration_date,
        )

When I save IdCard objects to the database, it behaves how I would expect:

print(expiration) # => datetime.date(2025, 10, 4)
new_id_card: SqlIdCard = SqlIdCard(expiration_date=expiration, card_number=num, owner_id=person.id)
# save to SQL, re-fetch object (to get auto-incremented ID), then:
es_person.id_card = EsIdCard.from_sql_id_card(new_id_card) # => EsIdCard(expiration_date=datetime.date(2025, 10, 4), ...)
es_person.save()
curl -X GET localhost:9200/people/_doc/123 -H "Content-Type: application/json" | python -m json.tool
{
    "_index": "people",
    "_id": "123",
    "...": "...",
    "_source": {
        "...": "...",
        "id_card": {
            "id": 1234,
            "card_number": "1234-5678",
            "expiration_date": "2025-10-04"
        }
    }
}

However, when I go to retrieve the person via the DSL class, the dates get casted into datetime objects:

person: EsPerson = EsPerson.get(id=123, index="people")
print(person.id_card.expiration_date) # => datetime.datetime(2025, 10, 4, 0, 0)

As a result, unless I manually re-cast the date fields to date, modifying the person and calling .save() throws an exception:

person.unrelated_attribute = "foo"
person.save() # => elasticsearch.BadRequestError: BadRequestError(400, 'document_parsing_exception', "[1:68] failed to parse field [id_card.expiration_date] of type [date] in document with id '123'. Preview of field's value: '2025-10-04T00:00:00'")

According to the type mapping documentation, this would seem to be an error. If anything, I would expect the reverse to occur (casting datetimes into dates) based on the type mapping table.

Is casting dates to datetimes the expected behavior? If so, should I be using a different type hint for dates that will never have times?

Edit: If I execute a search, the fields remain dates until they get converted into the DSL class:

results: Response = EsPerson.search(index="people").execute()
people: list[EsPerson] = list(results)
print(results.hits.hits[0]['_source']['id_card']['expiration_date']) # => '2025-10-04'
print(people[0].id_card.expiration_date) # => datetime.datetime(2025, 10, 4, 0, 0)
@lunalucadou lunalucadou changed the title Date objects being casted to datetimes when retrieved via .get() Dates being casted to datetimes on retrieved objects, causing parsing errors during updates Sep 12, 2024
@lunalucadou lunalucadou changed the title Dates being casted to datetimes on retrieved objects, causing parsing errors during updates Dates get casted to datetimes on retrieved objects, causing parsing errors during updates Sep 12, 2024
@miguelgrinberg
Copy link
Collaborator

miguelgrinberg commented Sep 13, 2024

Okay, yes, I can confirm that this is a bug introduced with the typing support. Looking into this.

Update: it's actually not a typing bug, you have stumbled upon something that has been broken for a very long time. I went as far back as version 7.4.1 and this bug is still there.

miguelgrinberg added a commit to miguelgrinberg/elasticsearch-dsl-py that referenced this issue Sep 13, 2024
miguelgrinberg added a commit to miguelgrinberg/elasticsearch-dsl-py that referenced this issue Sep 13, 2024
miguelgrinberg added a commit to miguelgrinberg/elasticsearch-dsl-py that referenced this issue Sep 13, 2024
miguelgrinberg added a commit to miguelgrinberg/elasticsearch-dsl-py that referenced this issue Sep 13, 2024
github-actions bot pushed a commit that referenced this issue Sep 13, 2024
miguelgrinberg added a commit that referenced this issue Sep 13, 2024
Fixes #1913

(cherry picked from commit 6db7e9d)

Co-authored-by: Miguel Grinberg <miguel.grinberg@gmail.com>
@lunalucadou
Copy link
Author

lunalucadou commented Sep 13, 2024

Thanks for the quick turnaround! I can confirm 8.15.3 has fixed the bug and I was able to discontinue the use of a workaround helper method that just re-casted datetimes back to dates.

miguelgrinberg added a commit to miguelgrinberg/elasticsearch-dsl-py that referenced this issue Dec 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Bug Something isn't right Priority: High
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants