diff --git a/AUTHORS b/AUTHORS index 17fae84ea..3292b5c3d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -266,3 +266,4 @@ that much better: * Terence Honles (https://github.com/terencehonles) * Sean Bermejo (https://github.com/seanbermejo) * Juan Gutierrez (https://github.com/juannyg) + * Gowtham V Bhat (https://github.com/gowthamvbhat) diff --git a/mongoengine/common.py b/mongoengine/common.py index 640384ec0..52cf3c98f 100644 --- a/mongoengine/common.py +++ b/mongoengine/common.py @@ -8,7 +8,7 @@ def _import_class(cls_name): Due to complications of circular imports mongoengine needs to do lots of inline imports in functions. This is inefficient as classes are imported repeated throughout the mongoengine code. This is - compounded by some recursive functions requiring inline imports. + compounded by some recursive functions requiring inline imports :mod:`mongoengine.common` provides a single point to import all these classes. Circular imports aren't an issue as it dynamically imports the diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index 2db97ddb7..64047ce36 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -733,7 +733,15 @@ def modify( query["$where"] = where_clause if not remove: - update = transform.update(queryset._document, **update) + if "__raw__" in update and isinstance( + update["__raw__"], list + ): # Case of Update with Aggregation Pipeline + update = [ + transform.update(queryset._document, **{"__raw__": u}) + for u in update["__raw__"] + ] + else: + update = transform.update(queryset._document, **update) sort = queryset._ordering try: diff --git a/tests/queryset/test_modify.py b/tests/queryset/test_modify.py index b96e05e63..d610fdb6c 100644 --- a/tests/queryset/test_modify.py +++ b/tests/queryset/test_modify.py @@ -130,6 +130,35 @@ class BlogPost(Document): ) assert blog.tags == ["python", "go", "rust", "code", "java"] + def test_modify_with_aggregation_update(self): + """Ensure that the 'aggregation_update' modify works correctly.""" + + class BlogPost(Document): + slug = StringField() + tags = ListField(StringField()) + + BlogPost.drop_collection() + + post = BlogPost(slug="test") + post.save() + + BlogPost.objects(slug="test").update( + __raw__=[{"$set": {"slug": {"$concat": ["$slug", " ", "$slug"]}}}], + ) + post.reload() + assert post.slug == "test test" + + post = BlogPost.objects(slug="test test").modify( + __raw__=[ + {"$set": {"slug": {"$concat": ["$slug", " ", "it"]}}}, # test test it + { + "$set": {"slug": {"$concat": ["When", " ", "$slug"]}} + }, # When test test it + ], + new=True, + ) + assert post.slug == "When test test it" + if __name__ == "__main__": unittest.main()