Removing null fields in the DynamoDB record - amazon-dynamodb

I am reading from a DynamoDB table in form of Map<String, AttributeValue>. The record looks something like this :-
{
"name": {
"s": "simran",
"n": null,
"b": null,
"m": null,
"l": null,
"ss": null,
"ns": null,
"bs": null,
"null": null,
"bool": null
},
"id": {
"s": "100",
"n": null,
"b": null,
"m": null,
"l": null,
"ss": null,
"ns": null,
"bs": null,
"null": null,
"bool": null
}
}
What i want to achieve is this :-
{
"name": {
"S": "simran"
},
"id": {
"S": "100"
}
}
The first JSON is extracted from this piece of code:-
com.amazonaws.services.dynamodbv2.model.Record inputRecord= inputRecord.getDynamodb().getNewImage()
Is there a AWS SDK that could be used for to convert the first JSON to the second model ? If i use this toString(), I get the JSON of this format (with unnecessary trailing commas after the attribute value), making the json invalid for further parsing:- { "name": { "s": "simran", }, "id": { "s": "100", } }

I used RecordMapper to serialise the value.
https://github.com/awslabs/dynamodb-streams-kinesis-adapter/blob/master/src/main/java/com/amazonaws/services/dynamodbv2/streamsadapter/model/RecordObjectMapper.java
ObjectMapper objectMapper = new RecordObjectMapper();
objectMapper.writeValueAsString()

Related

JsonPath: get root element depending on first level sub-element

I need all elements (including "id" and all attributes) of the json sample below where "type" has the value "state_machine_state", but only if "type" is on the first level. I don't want the middle element "order_transaction" in the result, although it has "type": "state_machine_state" in the second hierarchy level.
[
{
"id": "f45aa035eb424d26a0529d25b3647c32",
"type": "state_machine_state",
"attributes": {
"technicalName": "cancelled",
"name": "Cancelled",
"stateMachineId": "7553ad2630044fa589d786135d5000ad",
"customFields": null,
"createdAt": "2020-06-05T14:23:30.503+02:00",
"updatedAt": null,
"translated": {
"name": "Cancelled",
"customFields": []
},
"apiAlias": null
}
},
{
"id": "2d24ed4179824dbe92eee2f3d4f885b1",
"type": "order_transaction",
"relationships": {
"stateMachineState": {
"data": {
"type": "state_machine_state",
"id": "21f236e8955f45d3931fc9e44615088a"
}
}
},
"meta": null
},
{
"id": "d08e73da41b0473d83ea378a57a2fa1f",
"type": "state_machine_state",
"attributes": {
"technicalName": "completed",
"name": "Completed",
"stateMachineId": "7553ad2630044fa589d786135d5000ad",
"customFields": null,
"createdAt": "2020-06-05T14:23:30.482+02:00",
"updatedAt": null,
"translated": {
"name": "Completed",
"customFields": []
},
"apiAlias": null
},
"meta": null
}
]
With the query below I get all three elements
$..[?(#.type == 'state_machine_state')]
I just can't manage to select only the first level elements.
Could anyone please help?
Some implementations will allow you to select several items, but you're not going to be able to get the values with their keys.
For example, if you do
$..[?(#.type == 'state_machine_state')['id','attributes']
You'll just get a result set that contains all of the id values and all of the attributes values.
[
"f45aa035eb424d26a0529d25b3647c32",
{
"technicalName": "cancelled",
"name": "Cancelled",
"stateMachineId": "7553ad2630044fa589d786135d5000ad",
"customFields": null,
"createdAt": "2020-06-05T14:23:30.503+02:00",
"updatedAt": null,
"translated": {
"name": "Cancelled",
"customFields": []
},
"apiAlias": null
},
"2d24ed4179824dbe92eee2f3d4f885b1",
"d08e73da41b0473d83ea378a57a2fa1f",
{
"technicalName": "completed",
"name": "Completed",
"stateMachineId": "7553ad2630044fa589d786135d5000ad",
"customFields": null,
"createdAt": "2020-06-05T14:23:30.482+02:00",
"updatedAt": null,
"translated": {
"name": "Completed",
"customFields": []
},
"apiAlias": null
}
]
JSON Path isn't designed for transformation. JMES Path might be able to do what you're looking for, but I'm not as familiar with it.
Sometimes it helps to take a step back and think another way.
With this query I get exactly what I want:
$..[?(#.type == 'state_machine_state' && #.attributes)]
The elements I need have attributes, the others don't, so I just check for that in the filter.

Cosmos Nested JSON Query

This is the fist time that I work with CosmosDB and I am trying to create a Query to get some details about this JSON:
{
"Status": "Uploaded",
"ProvidedOn": "2022-04-04T18:34:57.4160484Z",
"DocumentTaxonomy": {
"JurisdictionalCountriesOfService": [
{
"Id": 5,
"Name": "United States"
}
],
"WorkProduct": {
"Id": 762,
"Name": "Other reports and documents",
"Type": "Info item"
}
},
"id": "3a92c052-bc23-4b8a-acbf-54044785968a",
"Meta": {
"VersionId": "3",
"LastUpdated": "0001-01-01T00:00:00",
"Source": null,
"Security": null,
"Tag": null,
"Id": null,
"Extension": null,
"ModifierExtension": null
},
}
Basicaly I need to get something like
SELECT id,Status,ProvidedOn, WorkProductName, WorkProductType,MetaVersionId FROM JSONFILE
In this image I am highlighting the columnsthat my query needs
NOTE: since I need to query different CosmoDB, not all of them have the DocumentTaxonomy section so the plan is when they doesn't exists return like a null or blank value
As per your question, the code should return the DocumentTaxonomy section values if they exist in the JSON otherwise It should return null or blank values.
This code may work for you:
SELECT c.id, c.ProvidedOn, c.Status,c.Meta.VersionId as versionId,
IS_DEFINED(c.DocumentTaxonomy.WorkProduct.Type) = true ? c.DocumentTaxonomy.WorkProduct.Type
: IS_DEFINED(c.DocumentTaxonomy.WorkProduct.Type) = false ? null
: "some default value"
as TypeDoc,
IS_DEFINED(c.DocumentTaxonomy.WorkProduct.Name) = true ? c.DocumentTaxonomy.WorkProduct.Name
: IS_DEFINED(c.DocumentTaxonomy.WorkProduct.Name) = false ? null
: "some default value"
as NameDoc
FROM c
The Output it gave when DocumentTaxonomy section exists is:
[
{
"id": "3a92c052-bc23-4b8a-acbf-54044785968a",
"ProvidedOn": "2022-04-04T18:34:57.4160484Z",
"Status": "Uploaded",
"versionId": "3",
"TypeDoc": "Info item",
"NameDoc": "Other reports and documents"
}
]
The Output when DocumentTaxonomy section not exists :
[
{
"id": "3a92c052-bc23-4b8a-acbf-54044785968a",
"ProvidedOn": "2022-04-04T18:34:57.4160484Z",
"Status": "Uploaded",
"versionId": "3",
"TypeDoc": null,
"NameDoc": null
}
]
Please check the screenshot of the output for your reference:

Azure Time Series Insights query: how to denote a variable such as 'cpu.thermal.average' in the query?

My series' got the value: cpu.thermal.average. I see the values in the TSI explorer for the given range of time.
By executing the following request, for "temperatures" I only get "null".
I am not sure about how to write $event.cpu.thermal.average equivalent.
Any idea?
{
"aggregateSeries": {
"timeSeriesId": [
"MySeries",
],
"searchSpan": {
"from": "2021-03-10T07:00:00Z",
"to": "2021-03-10T20:00:50Z"
},
"interval": "PT3600M",
"filter": null,
"inlineVariables": {
"latitudes": {
"kind": "numeric",
"value": {
"tsx": "$event.latitude"
},
"filter": null,
"aggregation": {
"tsx": "avg($value)"
}
},
"temperatures": {
"kind": "numeric",
"value": {
"tsx": "$event['cpu.thermal.average']"
},
"filter": null,
"aggregation": {
"tsx": "avg($value)"
}
}
},
"projectedVariables": [
"latitudes",
"temperatures"
]
}
}
From here: https://learn.microsoft.com/en-us/rest/api/time-series-insights/reference-time-series-expression-syntax#value-expressions
When accessing nested properties, the Type is required.
It should work if you use $event.cpu.thermal.average.Double

Updating item in DynamoDB fails for the UpdateExpression syntax

My table data looks like below one
{
"id": {
"S": "alpha-rocket"
},
"images": {
"SS": [
"apple/value:50",
"Mango/aa:284_454_51.0.0",
"Mango/bb:291",
"Mango/cc:4"
]
},
"product": {
"S": "fruit"
}
}
Below is my code to update table. The variables I am passing to function has values product_id has alpha-rocket, image_val has 284_454_53.0.0 and image has Mango/aa:284_454_53.0.0.
I am trying to update value of Mango/aa from 284_454_51.0.0 to 284_454_53.0.0 but getting an error "The document path provided in the update expression is invalid for update"
def update_player_score(product_id, image_val, image):
dynamo = boto3.resource('dynamodb')
tbl = dynamo.Table('<TableName>')
result = tbl.update_item(
expression_attribute_names: {
"#image_name" => "image_name"
},
expression_attribute_values: {
":image_val" => image_val,
},
key: {
"product" => "fruit",
"id" => product_id,
},
return_values: "ALL_NEW",
table_name: "orcus",
update_expression: "SET images.#image_val = :image_val",
}
Is there a way to update the value of Mango/aa or replace full string "Mango/aa:284_454_51.0.0" to "Mango/aa:284_454_53.0.0"
You cannot update a string in a list by matching the string. If you know the index of it you can replace the value of the string by index:
SET images[1] = : image_val
It seems like maybe what you want is not a list of strings, but another map. So instead of your data looking like it does you'd make it look like this, which would allow you to do the update you're looking for:
{
"id": {
"S": "alpha-rocket"
},
"images": {
"M": {
"apple" : {
"M": {
"value": {
"S": "50"
}
},
"Mango" : {
"M": {
"aa": {
"S": "284_454_51.0.0"
},
"bb": {
"S": "291"
},
"cc": {
"S": "4"
}
}
}
},
"product": {
"S": "fruit"
}
}
I would also consider putting the different values in different "rows" in the table and using queries to build the objects.

How to validated pointer in json.net?

Hello I have the following scenario:
JSON object:
{
"$id": "1",
"someProp": "123",
"children": [{
"$id": "2",
"$type": "ClassB",
"Parent": {
"$ref": "1"
}
}]
}
JSON schema :
{
"id": "ClassA",
"required": true,
"type": [
"object",
"null"
],
"properties": {
"someProp": {
"required": true,
"type": [
"string",
"null"
]
},
"children": {
"id": "List<Child>",
"required": true,
"type": [
"array",
"null"
],
"items": {
"id": "Child",
"type": [
"object",
"null"
],
"properties": {
"id": {
"required": true,
"type": "integer"
},
"parent": {
"$ref": "ClassA"
}
}
}
}
}
}
I have a complex object who has reference loops, so I have configured json.net to make reference when the object is serialized. Everything is working as expected I can serialize and deserialize the object, but when I am validating the JSON object with the above schema I got the following error :
Required properties are missing from object : "someProp", path :
object.Children[0].parent
And that is correct how can make the schema look at the reference JSON object ?
Problem is with the "id" property of an object inside children array
"properties": {
"id": {
"required": true,
"type": "integer"
},
"parent": {
"$ref": "ClassA"
}
}
You are saying id requires to have property "id" and you don't have that property inside object, either changes "id" to "$id" or remove it from property list to satisfy schema.
"properties": {
"$id": {
"required": true,
"type": "integer"
},
"parent": {
"$ref": "ClassA"
}
}
Also make sure you have "id" / "$id" integer value, i.e.
"$id":2 not "$id":"2"

Resources