Azure CosmosDB - Partial Document Update (Patch) on Complex Structures - azure-cosmosdb

I'm trying to use the Partial Document Update (Patch API) to update a child object in my document, but I'm running into trouble. I found this Stack Overflow question which is the same question that I have. However, the accepted answer resolves the problem by referring to an object in an array by index. I don't believe that I have the luxury of being able to do that. So, to use the same example document as the other question...
{
"id": "SalesOrder2",
"ponumber": "PO15428132599",
"OrderDate": "2005-07-01T00:00:00",
"DueDate": "2005-07-13T00:00:00",
"ShippedDate": "2005-07-08T00:00:00",
"AccountNumber": "Account2",
"SubTotal": 6107.082,
"TaxAmt": 586.1203,
"Freight": 183.1626,
"TotalDue": 4893.3929,
"DiscountAmt": 1982.872,
"Items": [
{
"Id": 1,
"OrderQty": 3,
"ProductCode": "A-123",
"ProductName": "Product 1",
"CurrencySymbol": "$",
"CurrencyCode": "USD",
"UnitPrice": 17.1,
"LineTotal": 5.7
},
{
"Id": 2,
"OrderQty": 2,
"ProductCode": "A-456",
"ProductName": "Product 2",
"CurrencySymbol": "$",
"CurrencyCode": "USD",
"UnitPrice": 10,
"LineTotal": 20
}
],
"_rid": "BsMkAMc43s4CAAAAAAAAAA==",
"_self": "dbs/BsMkAA==/colls/BsMkAMc43s4=/docs/BsMkAMc43s4CAAAAAAAAAA==/",
"_etag": "\"00000000-0000-0000-e136-0dbec04601d7\"",
"_attachments": "attachments/",
"_ts": 1637760030
}
I have no guarantee that the item in the Items array with an Id of 1 would be in position 0 of the array. Similarly, the item with an Id of 2 is not guaranteed to be in position 1. Therefore I believe that I need to use the FilterPredicate parameter of the Patch API to filter my results. But when I attempt to do that, I keep getting the following exception:
Microsoft.Azure.Cosmos.CosmosException : Response status code does not
indicate success: PreconditionFailed (412); Substatus: 1110;
ActivityId: dbd258ae-0a0a-4a9b-8c25-1d36e137b7c5; Reason: ();
Any assistance you could provide on how to accomplish this would be appreciated.

As i answered in the attached link, Patch requires the user to pass the specific index of the object needs to be updated. We are working on enabling this particular feature in the coming months, However as an alternative, you should look at Conditional Patch
Code will be something like this,
response = patch(operation, Condition(check if item exists))
if(response == fail/precondition failed)
{
PatchOperation operation = PatchOperation.Add("/Items", [{"Id" : "P-1", "Description" : "My Product"}]);
}

Related

Firestore Pagination : how to set Cursor for startAt using Rest Api

I'm using firebase firestore using Rest API to get data limited by 5 documents only, ordered by a field called LikesCount.
When I want to fetch the next 5 documents I have to use startAt and pass the LikesCount value of the last document from the first 5 documents.
But in this way, it will fetch wrong data when there is another document with the same LikesCount value So I tried and searched a lot about how to pass the last Document id in addition to the LikesCount value But all of them did not work In addition, I tested the pagination using the Web SDK and it was working correctly because you can pass the document snapshot easily, but what does the document snapshot object include? So that we can understand the structure of the Cursor and apply it to the REST API.
I tried to use this method to pass the Document ID as referenceValue
{
"structuredQuery": {
"from": [{
"collectionId": "Users"
}],
"where": {
"compositeFilter": {
"op": "AND",
"filters": []
}
},
"orderBy": [{
"field": {
"fieldPath": "LikesCount"
},
"direction": "DESCENDING"
}],
"startAt":
{ "values": [
{
"integerValue": "6"
},
{
"referenceValue": "projects/myprojectid/databases/(default)/documents/Posts/xEvmJ1LLHwTKVREQfXtX"
}
],
"before": false
},
"limit":5
}
}
But an error will occur : Cursor has too many values.
also, I tried to pass only the referenceValue and it still did not return the correct 5 documents.
Thanks in advance :)
Your orderBy() has 1 field (LikesCount) but your startAt() has 2 fields. I suspect that is the reason for the error message?
Passing the integerValue won't work. If there are 13 results with the value 6, then each time you make the above call you'd get the same first 5 results.
When you say:
I tried only passing the referenceValue and still did not get the correct 5 documents
what documents are you getting? What documents were you expecting to get?

Issues de-serializing from CosmosDB when migrating from MongoDB.Driver to Azure DocumentClient

I'm am trying to re-implement a class which reads from Azure CosmosDB using the Microsoft.Azure.Documents.Client.DocumentClient so that I can make use of the continuation token functionality.
However, when I try to retrieve data I get the following error:
Error converting value \"NWE2OGY5MzYzMmY0OGIlM2Ix\" to type
'MongoDB.Bson.ObjectId'
To begin with this isn't on of our id values, but I tried to implement an ObjectIdConverter as detailed here, but then started getting this error:
String should contain only hexadecimal digits.
As the value it's trying to use doesn't actuall correspond to an entry id.
I then put in a JsonConverter for the actual object I'm trying to de-serialize to and and loaded the json into a JObject so I could see what I'm dealing with.
The structure doesn't match what I expect or what I see in Robo 3T:
{{
"$t": 3,
"$v": {
"_id": {
"$t": 7,
"$v": "ù62ô;Üöã±"
},
"Channel": {
"$t": 2,
"$v": "channel"
},
"TopicRoutingKey": {
"$t": 18,
"$v": 123,
"$s": "123"
},
"SequenceNumber": {
"$t": 18,
"$v": 1,
"$s": "1"
},
"CorrelationId": {
"$t": 5,
"$v": "00000006\u0003Ù\bÜ\"²f#\u085L+SæÝ"
},
"Message": {
"$t": 2,
"$v": "2gIUCJSAOBGMCv1eTLCAHKJ2QjhUx/iCtT5t0YsfS10JIsIJSAOQ=="
}
},
"id": "NWE2OGY5MzmRjZjZlM2Ix",
"_rid": "znt6AKAAAAAAAAA==",
"_self": "dbs/znt6AA==/colls/znt6AK0j8AU=/docs/znt6AKAAAAAAAAA==/",
"_etag": "\"3b02af0b-0000-0000-0000-5a68f9370000\"",
"_attachments": "attachments/",
"_ts": 1516828983
}}
I'm assuming these are type / value tuples and I can see the data I want is in the root $v: but I can't figure out how to de-serialize this (short of replicating the data structure myself and then de-serializing to it, then converting to my actual data structure which seems like it shouldn't be necessary).
Can anyone tell me what is going on here?

Workfront API: Human readable status for Issues and Projects

https://support.workfront.com/hc/en-us/articles/115003574147-API-Basics
https://support.workfront.com/hc/en-us/categories/202718477
Querying objects (i.e.: GET /attask/api/v9.0/project/4c78821c0000d6fa8d5e52f07a1d54d0) returns a response similar to the following:
..
"status": "INP",
...
How do you get human readable statuses form these responses? Do you hard-code all possible values, or, can it be achieved using queries?
i.e.: "INP" > "In Progress"
You can pull these values from the Custom Enumeration tables (CSTEM). For example, this will return all the task descriptions:
https://subdomain.my.workfront.com/attask/api/v9.0/CSTEM/search?apiKey={{apiKey}}&fields=*&enumClass=STATUS_TASK&enumClass_Mod=in
You will get something like this:
{
"color": "FF3939",
"equatesWith": "CPL",
"groupID": "5419c94f00004a056282a15eed58e47f",
"label": "Complete",
"objCode": "CSTEM",
"value": "CPL",
"ID": "57ed3a2000477cfb7368beb5d995bf88",
"customerID": "540f5a3f0019b...",
"description": "Task is fully completed",
"enumClass": "STATUS_TASK",
"extRefID": null,
"isPrimary": true,
"valueAsInt": null,
"valueAsString": "CPL"
},
For issues use "STATUS_OPTASK".
I created a dictionary and translating the statuses while reading the short version (INP > In Progress)

WooCommerce REST API: updating order line item metadata for shipment

I've stubled upon an issue for updating order line items' metadata via WooCommerce REST API using node.js.
I've been following these steps for updating orders (and was succesful with some fields):
https://woocommerce.github.io/woocommerce-rest-api-docs/#update-an-order
Now, what I would like to achieve is changing the number of shipped line items of an order. Something I would normally use the partial orders WC plugin in the wordpress UI.
Below, you can find a screenshot of a line item I get from WC using the orders API call. The last element of the meta_data array has key 'shipped' and it contains an array with one object, stating that one (out of two ordered items) had been shipped:
"line_items": [{
"id": 1937,
"name": "Maya",
"product_id": 1271,
"variation_id": 1272,
"quantity": 2,
"tax_class": "",
"subtotal": "140.00",
"subtotal_tax": "0.00",
"total": "140.00",
"total_tax": "0.00",
"taxes": [],
"meta_data": [{
"id": 21637,
"key": "pa_product-color",
"value": "beige"
}, {
"id": 21638,
"key": "pa_shoe-size",
"value": "42"
}, {
"id": 21639,
"key": "pa_shoe-width",
"value": "wide"
}, {
"id": 21640,
"key": "shipped",
"value": [{
"qty": 1,
"date": "Nov 21, 2017"
}
]
}
],
"sku": "2522BE42W",
"price": 70
},
As you can see, the value of the key 'shipped' is an object. When I ty to send it (back) to WC, I get an error saying:
"data":{"status":400,"params":{"line_items":"line_items[0][meta_data][3][value] is not of type string."}}}
When I try to send the value as a string, i.e.
lineItems[0].meta_data = [{key:"shipped", value: "[{qty:'2'}]" }]
I get no errors, but WC treats this as string, not as an object and doesn't update the shipment qty in the DB the way I intended (it only pulls the shipped quantity down to 0 instead):
{
"id": 21640,
"key": "shipped",
"value": "[{qty:'2'}]"
}
Any insights or ideas - how could I modify the shipped quantity of line items via the WC API?
So, apparently there was a bug in WP 4.9 version, which was fixed recently in the following commit:
https://github.com/woocommerce/woocommerce/pull/17849
It concerns REST API schema and after merging the fix to WooCommerce, the problems disappear and now I am able to send the data as an object.
More on the topic can be found here:
https://github.com/woocommerce/wc-api-dev/pull/74

Serialized Entities displaying only ID

I'm using JMSSerializer and FOSRestBundle. I have a fairly typical object graph, including some recursion.
What I would like to accomplish is that included objects beyond a certain depth or in general are listed only with their ID, but when serialized directly, with all data.
So, for example:
Users => Groups => Users
when requesting /user/1 the result should be something like
{ "id": 1, "name": "John Doe", "groups": [ { "id": 10 }, { "id": 11 } ] }
While when I request /group/10 it would be:
{ "id": 10, "name": "Groupies", "users": [ { "id": 1 }, { "id": 2 }, { "id": 4 } ] }
With #MaxDeph I can hide the included arrays completely, so I get
{ "id": 1, "name": "John Doe", "groups": [] }
But I would like to include just the IDs so that the REST client can fetch them if it needs them, or consult his cache, or do whatever.
I know I can manually cobble this together using groups, but for consistency reasons I was wondering if I can somehow enable this behaviour in my entire application, maybe even with a reference to maxdepth so I can control where to include IDs and where to include full objects?
For the sake of those finding this:
I found no other solution, but doing this with groups works just fine and gives me the result I was looking for.

Resources