From 26401a9d5d93cd3706f17b0aeb6d4f689de50b51 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Wed, 8 May 2024 18:56:55 +0100 Subject: [PATCH] Document.update() should accept fields set to None or empty Fixes #1819 --- elasticsearch_dsl/_async/document.py | 2 +- elasticsearch_dsl/_sync/document.py | 2 +- .../test_integration/_async/test_document.py | 27 +++++++++++++++++++ tests/test_integration/_sync/test_document.py | 27 +++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/elasticsearch_dsl/_async/document.py b/elasticsearch_dsl/_async/document.py index 23d3c282..89ed06f4 100644 --- a/elasticsearch_dsl/_async/document.py +++ b/elasticsearch_dsl/_async/document.py @@ -295,7 +295,7 @@ async def update( merge(self, fields) # prepare data for ES - values = self.to_dict() + values = self.to_dict(skip_empty=False) # if fields were given: partial update body["doc"] = {k: values.get(k) for k in fields.keys()} diff --git a/elasticsearch_dsl/_sync/document.py b/elasticsearch_dsl/_sync/document.py index 7567ff1a..c851c8e8 100644 --- a/elasticsearch_dsl/_sync/document.py +++ b/elasticsearch_dsl/_sync/document.py @@ -293,7 +293,7 @@ def update( merge(self, fields) # prepare data for ES - values = self.to_dict() + values = self.to_dict(skip_empty=False) # if fields were given: partial update body["doc"] = {k: values.get(k) for k in fields.keys()} diff --git a/tests/test_integration/_async/test_document.py b/tests/test_integration/_async/test_document.py index e18b9467..e1e69f55 100644 --- a/tests/test_integration/_async/test_document.py +++ b/tests/test_integration/_async/test_document.py @@ -120,6 +120,13 @@ class Index: name = "test-serialization" +class Tags(AsyncDocument): + tags = Keyword(multi=True) + + class Index: + name = "tags" + + @pytest.mark.asyncio async def test_serialization(async_write_client): await SerializationDoc.init() @@ -504,6 +511,26 @@ async def test_save_updates_existing_doc(async_data_client): assert new_repo["_seq_no"] == elasticsearch_repo.meta.seq_no +@pytest.mark.asyncio +async def test_update_empty_field(async_client): + await Tags._index.delete(ignore_unavailable=True) + await Tags.init() + d = Tags(id="123", tags=["a", "b"]) + await d.save(wait_for_active_shards=1) + await d.update(tags=[]) + assert d.tags == [] + + while True: + try: + r = await Tags.search().execute() + d = r.hits[0] + except IndexError: + continue + else: + break + assert d.tags == [] + + @pytest.mark.asyncio async def test_save_automatically_uses_seq_no_and_primary_term(async_data_client): elasticsearch_repo = await Repository.get("elasticsearch-dsl-py") diff --git a/tests/test_integration/_sync/test_document.py b/tests/test_integration/_sync/test_document.py index 16f39ad9..7a4849d7 100644 --- a/tests/test_integration/_sync/test_document.py +++ b/tests/test_integration/_sync/test_document.py @@ -120,6 +120,13 @@ class Index: name = "test-serialization" +class Tags(Document): + tags = Keyword(multi=True) + + class Index: + name = "tags" + + @pytest.mark.sync def test_serialization(write_client): SerializationDoc.init() @@ -498,6 +505,26 @@ def test_save_updates_existing_doc(data_client): assert new_repo["_seq_no"] == elasticsearch_repo.meta.seq_no +@pytest.mark.sync +def test_update_empty_field(client): + Tags._index.delete(ignore_unavailable=True) + Tags.init() + d = Tags(id="123", tags=["a", "b"]) + d.save(wait_for_active_shards=1) + d.update(tags=[]) + assert d.tags == [] + + while True: + try: + r = Tags.search().execute() + d = r.hits[0] + except IndexError: + continue + else: + break + assert d.tags == [] + + @pytest.mark.sync def test_save_automatically_uses_seq_no_and_primary_term(data_client): elasticsearch_repo = Repository.get("elasticsearch-dsl-py")