Skip to content

Commit 544c1a3

Browse files
committed
Python snippets added, doc made more generic
1 parent b1c193f commit 544c1a3

File tree

1 file changed

+132
-3
lines changed

1 file changed

+132
-3
lines changed

articles/cosmos-db/nosql/transactional-batch.md

Lines changed: 132 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,140 @@ if (response.isSuccessStatusCode())
138138
> [!IMPORTANT]
139139
> If there's a failure, the failed operation will have a status code of its corresponding error. All the other operations will have a 424 status code (failed dependency). If the operation fails because it tries to create an item that already exists, a status code of 409 (conflict) is returned. The status code enables one to identify the cause of transaction failure.
140140
141+
### [Python](#tab/python)
142+
143+
Get or create a container instance:
144+
145+
```python
146+
container = database.create_container_if_not_exists(id="batch_container",
147+
partition_key=PartitionKey(path='/road_bikes'))
148+
```
149+
In Python, Transactional Batch operations look very similar to the singular operations apis, and are tuples containing (operation_type_string, args_tuple, batch_operation_kwargs_dictionary). Below are sample items that will be used to demonstrate batch operations functionality:
150+
151+
```python
152+
153+
create_demo_item = {
154+
"id": "68719520766",
155+
"category": "road-bikes",
156+
"name": "Chropen Road Bike"
157+
}
158+
159+
# for demo, assume that this item already exists in the container.
160+
# the item id will be used for read operation in the batch
161+
read_demo_item1 = {
162+
"id": "68719519884",
163+
"category": "road-bikes",
164+
"name": "Tronosuros Tire",
165+
"productId": "68719520766"
166+
}
167+
168+
# for demo, assume that this item already exists in the container.
169+
# the item id will be used for read operation in the batch
170+
read_demo_item2 = {
171+
"id": "68719519886",
172+
"category": "road-bikes",
173+
"name": "Tronosuros Tire",
174+
"productId": "68719520766"
175+
}
176+
177+
# for demo, assume that this item already exists in the container.
178+
# the item id will be used for read operation in the batch
179+
read_demo_item3 = {
180+
"id": "68719519887",
181+
"category": "road-bikes",
182+
"name": "Tronosuros Tire",
183+
"productId": "68719520766"
184+
}
185+
186+
# for demo, we'll upsert the item with id 68719519885
187+
upsert_demo_item = {
188+
"id": "68719519885",
189+
"category": "road-bikes",
190+
"name": "Tronosuros Tire Upserted",
191+
"productId": "68719520768"
192+
}
193+
194+
# for replace demo, we'll replace the read_demo_item2 with this item
195+
replace_demo_item = {
196+
"id": "68719519886",
197+
"category": "road-bikes",
198+
"name": "Tronosuros Tire replaced",
199+
"productId": "68719520769"
200+
}
201+
202+
# for replace with etag match demo, we'll replace the read_demo_item3 with this item
203+
# The use of etags and if-match/if-none-match options allows users to run conditional replace operations
204+
# based on the etag value passed. When using if-match, the request will only succeed if the item's latest etag
205+
# matches the passed in value. For more on optimistic concurrency control, see the link below:
206+
# https://learn.microsoft.com/azure/cosmos-db/nosql/database-transactions-optimistic-concurrency
207+
replace_demo_item_if_match_operation = {
208+
"id": "68719519887",
209+
"category": "road-bikes",
210+
"name": "Tronosuros Tireh",
211+
"wasReplaced": "Replaced based on etag match"
212+
"productId": "68719520769"
213+
}
214+
215+
```
216+
217+
Prepare the operations to be added to the batch:
218+
219+
```python
220+
create_item_operation = ("create", (create_demo_item,), {})
221+
read_item_operation = ("read", ("68719519884",), {})
222+
delete_item_operation = ("delete", ("68719519885",), {})
223+
upsert_item_operation = ("upsert", (upsert_demo_item,), {})
224+
replace_item_operation = ("replace", ("68719519886", replace_demo_item), {})
225+
replace_item_if_match_operation = ("replace",
226+
("68719519887", replace_demo_item_if_match_operation),
227+
{"if_match_etag": container.client_connection.last_response_headers.get("etag")})
228+
```
229+
Add the operations to the batch:
230+
231+
```python
232+
batch_operations = [
233+
create_item_operation,
234+
read_item_operation,
235+
delete_item_operation,
236+
upsert_item_operation,
237+
replace_item_operation,
238+
replace_item_if_match_operation
239+
]
240+
```
241+
242+
Finally, execute the batch:
243+
244+
```python
245+
try:
246+
# Run that list of operations
247+
batch_results = container.execute_item_batch(batch_operations=batch_operations, partition_key="road_bikes")
248+
# Batch results are returned as a list of item operation results - or raise a CosmosBatchOperationError if
249+
# one of the operations failed within your batch request.
250+
print("\nResults for the batch operations: {}\n".format(batch_results))
251+
except exceptions.CosmosBatchOperationError as e:
252+
error_operation_index = e.error_index
253+
error_operation_response = e.operation_responses[error_operation_index]
254+
error_operation = batch_operations[error_operation_index]
255+
print("\nError operation: {}, error operation response: {}\n".format(error_operation, error_operation_response))
256+
# [END handle_batch_error]
257+
```
258+
> **Note for using patch operation and replace_if_match_etag operation in the batch** <br>
259+
The batch operation kwargs dictionary is limited, and only takes a total of three different key values. In the case of wanting to use conditional patching within the batch, the use of filter_predicate key is available for the patch operation, or in case of wanting to use etags with any of the operations, the use of the if_match_etag/if_none_match_etag keys is available as well.<br>
260+
>```python
261+
> batch_operations = [
262+
> ("replace", (item_id, item_body), {"if_match_etag": etag}),
263+
> ("patch", (item_id, operations), {"filter_predicate": filter_predicate, "if_none_match_etag": etag}),
264+
> ]
265+
>```
266+
267+
268+
> [!IMPORTANT]
269+
> If there's a failure, the failed operation will have a status code of its corresponding error. All the other operations will have a 424 status code (failed dependency). If the operation fails because it tries to create an item that already exists, a status code of 409 (conflict) is returned. The status code enables one to identify the cause of transaction failure.
141270
---
142271
143272
## How are transactional batch operations executed
144273
145-
When the `ExecuteAsync` method is called, all operations in the `TransactionalBatch` object are grouped, serialized into a single payload, and sent as a single request to the Azure Cosmos DB service.
274+
When the Transactional Batch is executed, all operations in the Transactional Batch are grouped, serialized into a single payload, and sent as a single request to the Azure Cosmos DB service.
146275
147276
The service receives the request and executes all operations within a transactional scope, and returns a response using the same serialization protocol. This response is either a success, or a failure, and supplies individual operation responses per operation.
148277
@@ -152,8 +281,8 @@ The SDK exposes the response for you to verify the result and, optionally, extra
152281
153282
Currently, there are two known limits:
154283
155-
* The Azure Cosmos DB request size limit constrains the size of the `TransactionalBatch` payload to not exceed 2 MB, and the maximum execution time is 5 seconds.
156-
* There's a current limit of 100 operations per `TransactionalBatch` to ensure the performance is as expected and within SLAs.
284+
* The Azure Cosmos DB request size limit constrains the size of the Transactional Batch payload to not exceed 2 MB, and the maximum execution time is 5 seconds.
285+
* There's a current limit of 100 operations per Transactional Batch to ensure the performance is as expected and within SLAs.
157286
158287
## Next steps
159288

0 commit comments

Comments
 (0)