From 3e1c83f8fab28c37ab2e25eab2d7dcc6121f50cc Mon Sep 17 00:00:00 2001 From: Johnny Chang Date: Tue, 4 Aug 2020 00:30:15 +0800 Subject: [PATCH 1/2] Fix query transformation regarding special operators --- mongoengine/fields.py | 3 +++ tests/queryset/test_transform.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index b05e726a..f50e6045 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -773,6 +773,9 @@ class EmbeddedDocumentField(BaseField): def prepare_query_value(self, op, value): if value is not None and not isinstance(value, self.document_type): + # Short circuit for special operators, returning them as is + if isinstance(value, dict) and all(k.startswith('$') for k in value.keys()): + return value try: value = self.document_type._from_son(value) except ValueError: diff --git a/tests/queryset/test_transform.py b/tests/queryset/test_transform.py index 8d6c2d06..0fba3975 100644 --- a/tests/queryset/test_transform.py +++ b/tests/queryset/test_transform.py @@ -344,6 +344,36 @@ class TestTransform(unittest.TestCase): ) assert update == {"$pull": {"content.text": {"word": {"$nin": ["foo", "bar"]}}}} + def test_transform_embedded_document_list_fields(self): + """ + Test added to check filtering + EmbeddedDocumentListField which is inside a EmbeddedDocumentField + """ + + class Drink(EmbeddedDocument): + id = StringField() + meta = { + 'strict': False + } + + class Shop(Document): + drinks = EmbeddedDocumentListField(Drink) + + Shop.drop_collection() + drinks = [Drink(id='drink_1'), Drink(id='drink_2')] + Shop.objects.create(drinks=drinks) + q_obj = transform.query( + Shop, + drinks__all=[{'$elemMatch': {'_id': x.id}} for x in drinks] + ) + assert q_obj == { + 'drinks': { + '$all': [{'$elemMatch': {'_id': x.id}} for x in drinks] + } + } + + Shop.drop_collection() + if __name__ == "__main__": unittest.main() From 7116dec74a394900d2ffd9bcca5b3318d03598aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastien=20G=C3=A9rard?= Date: Tue, 11 Aug 2020 21:55:22 +0200 Subject: [PATCH 2/2] run black to please ci --- mongoengine/fields.py | 2 +- tests/queryset/test_transform.py | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/mongoengine/fields.py b/mongoengine/fields.py index f50e6045..8fdeae15 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -774,7 +774,7 @@ class EmbeddedDocumentField(BaseField): def prepare_query_value(self, op, value): if value is not None and not isinstance(value, self.document_type): # Short circuit for special operators, returning them as is - if isinstance(value, dict) and all(k.startswith('$') for k in value.keys()): + if isinstance(value, dict) and all(k.startswith("$") for k in value.keys()): return value try: value = self.document_type._from_son(value) diff --git a/tests/queryset/test_transform.py b/tests/queryset/test_transform.py index 0fba3975..f5d248af 100644 --- a/tests/queryset/test_transform.py +++ b/tests/queryset/test_transform.py @@ -352,24 +352,19 @@ class TestTransform(unittest.TestCase): class Drink(EmbeddedDocument): id = StringField() - meta = { - 'strict': False - } + meta = {"strict": False} class Shop(Document): drinks = EmbeddedDocumentListField(Drink) Shop.drop_collection() - drinks = [Drink(id='drink_1'), Drink(id='drink_2')] + drinks = [Drink(id="drink_1"), Drink(id="drink_2")] Shop.objects.create(drinks=drinks) q_obj = transform.query( - Shop, - drinks__all=[{'$elemMatch': {'_id': x.id}} for x in drinks] + Shop, drinks__all=[{"$elemMatch": {"_id": x.id}} for x in drinks] ) assert q_obj == { - 'drinks': { - '$all': [{'$elemMatch': {'_id': x.id}} for x in drinks] - } + "drinks": {"$all": [{"$elemMatch": {"_id": x.id}} for x in drinks]} } Shop.drop_collection()