@@ -2526,55 +2526,37 @@ async def async_update(
25262526 :param upsert: insert if document doesn't exist (default False)
25272527 :param multi: update multiple documents (default True)
25282528 :param write_concern: write concern options
2529- :param update: update operations to perform
2529+ :param update: Django-style update keyword arguments
25302530 :returns: number of documents affected
25312531 """
25322532 from mongoengine .connection import DEFAULT_CONNECTION_NAME
25332533
25342534 alias = self ._document ._meta .get ("db_alias" , DEFAULT_CONNECTION_NAME )
25352535 ensure_async_connection (alias )
25362536
2537- if not update :
2538- raise OperationError ("No update parameters passed " )
2537+ if not update and not upsert :
2538+ raise OperationError ("No update parameters, would remove data " )
25392539
25402540 queryset = self .clone ()
25412541 query = queryset ._query
25422542
2543- # Process the update dict to handle field names and operators
2544- update_dict = {}
2545- for key , value in update .items ():
2546- # Handle operators like inc__field, set__field, etc.
2547- if "__" in key and key .split ("__" )[0 ] in [
2548- "inc" ,
2549- "set" ,
2550- "unset" ,
2551- "push" ,
2552- "pull" ,
2553- "pull_all" ,
2554- "addToSet" ,
2555- ]:
2556- op , field = key .split ("__" , 1 )
2557- # Convert pull_all to pullAll for MongoDB
2558- if op == "pull_all" :
2559- mongo_op = "$pullAll"
2560- else :
2561- mongo_op = f"${ op } "
2562- if mongo_op not in update_dict :
2563- update_dict [mongo_op ] = {}
2564- field_name = queryset ._document ._translate_field_name (field )
2565- update_dict [mongo_op ][field_name ] = value
2566- elif key .startswith ("$" ):
2567- # Direct MongoDB operator
2568- update_dict [key ] = {}
2569- for field_name , field_value in value .items ():
2570- field_name = queryset ._document ._translate_field_name (field_name )
2571- update_dict [key ][field_name ] = field_value
2543+ # Use transform.update to handle all operators consistently with sync version
2544+ if "__raw__" in update and isinstance (update ["__raw__" ], list ):
2545+ # Case of Update with Aggregation Pipeline
2546+ update_dict = [
2547+ transform .update (queryset ._document , ** {"__raw__" : u })
2548+ for u in update ["__raw__" ]
2549+ ]
2550+ else :
2551+ update_dict = transform .update (queryset ._document , ** update )
2552+
2553+ # If doing an atomic upsert on an inheritable class
2554+ # then ensure we add _cls to the update operation
2555+ if upsert and "_cls" in query :
2556+ if "$set" in update_dict :
2557+ update_dict ["$set" ]["_cls" ] = queryset ._document ._class_name
25722558 else :
2573- # Direct field update - wrap in $set
2574- if "$set" not in update_dict :
2575- update_dict ["$set" ] = {}
2576- key = queryset ._document ._translate_field_name (key )
2577- update_dict ["$set" ][key ] = value
2559+ update_dict ["$set" ] = {"_cls" : queryset ._document ._class_name }
25782560
25792561 collection = await self ._async_get_collection ()
25802562
0 commit comments