@@ -1164,6 +1164,79 @@ def response_handler(resp: Response) -> Cursor:
1164
1164
1165
1165
return await self ._executor .execute (request , response_handler )
1166
1166
1167
+ async def update_match (
1168
+ self ,
1169
+ filters : Json ,
1170
+ body : T ,
1171
+ limit : Optional [int | str ] = None ,
1172
+ keep_none : Optional [bool ] = None ,
1173
+ wait_for_sync : Optional [bool ] = None ,
1174
+ merge_objects : Optional [bool ] = None ,
1175
+ allow_dirty_read : Optional [bool ] = None ,
1176
+ ) -> Result [int ]:
1177
+ """Update matching documents.
1178
+
1179
+ Args:
1180
+ filters (dict | None): Query filters.
1181
+ body (dict): Full or partial document body with the updates.
1182
+ limit (int | str | None): Maximum number of documents to return.
1183
+ keep_none (bool | None): If set to `True`, fields with value `None` are
1184
+ retained in the document. Otherwise, they are removed completely.
1185
+ wait_for_sync (bool | None): Wait until operation has been synced to disk.
1186
+ merge_objects (bool | None): If set to `True`, sub-dictionaries are merged
1187
+ instead of the new one overwriting the old one.
1188
+ allow_dirty_read (bool | None): Allow reads from followers in a cluster.
1189
+
1190
+ Returns:
1191
+ int: Number of documents updated.
1192
+
1193
+ Raises:
1194
+ DocumentUpdateError: If update fails.
1195
+ """
1196
+ if not self ._is_none_or_dict (filters ):
1197
+ raise ValueError ("filters parameter must be a dict" )
1198
+ if not (self ._is_none_or_int (limit ) or limit == "null" ):
1199
+ raise ValueError ("limit parameter must be a non-negative int" )
1200
+
1201
+ # If the waitForSync parameter is not specified or set to false,
1202
+ # then the collection’s default waitForSync behavior is applied.
1203
+ sync = f", waitForSync: { wait_for_sync } " if wait_for_sync is not None else ""
1204
+ query = f"""
1205
+ FOR doc IN @@collection
1206
+ { self ._build_filter_conditions (filters )}
1207
+ { f"LIMIT { limit } " if limit is not None else "" }
1208
+ UPDATE doc WITH @body IN @@collection
1209
+ OPTIONS {{ keepNull: @keep_none, mergeObjects: @merge { sync } }}
1210
+ """ # noqa: E201 E202
1211
+ bind_vars = {
1212
+ "@collection" : self .name ,
1213
+ "body" : body ,
1214
+ "keep_none" : keep_none ,
1215
+ "merge" : merge_objects ,
1216
+ }
1217
+ data = {"query" : query , "bindVars" : bind_vars }
1218
+ headers : RequestHeaders = {}
1219
+ if allow_dirty_read is not None :
1220
+ if allow_dirty_read is True :
1221
+ headers ["x-arango-allow-dirty-read" ] = "true"
1222
+ else :
1223
+ headers ["x-arango-allow-dirty-read" ] = "false"
1224
+
1225
+ request = Request (
1226
+ method = Method .POST ,
1227
+ endpoint = "/_api/cursor" ,
1228
+ data = self .serializer .dumps (data ),
1229
+ headers = headers ,
1230
+ )
1231
+
1232
+ def response_handler (resp : Response ) -> int :
1233
+ if resp .is_success :
1234
+ result = self .deserializer .loads (resp .raw_body )
1235
+ return cast (int , result ["extra" ]["stats" ]["writesExecuted" ])
1236
+ raise DocumentUpdateError (resp , request )
1237
+
1238
+ return await self ._executor .execute (request , response_handler )
1239
+
1167
1240
async def insert_many (
1168
1241
self ,
1169
1242
documents : Sequence [T ],
0 commit comments