I'm trying to update a Couchbase doc from one structure to another
here is the current structure
{
"config": {
"160x600": {
"siteId": "123455677"
},
"300x250": {
"siteId": "123455677"
},
"300x600": {
"siteId": "123455677"
}
}
}
Desired structure is
{
"config": {
"160x600": {
"siteId": "123455677",
"size":[160,600]
},
"300x250": {
"siteId": "123455677",
"size" : [300,250]
},
"300x600": {
"siteId": "123455677",
"size": [300,600]
}
}
}
Basically I wants to iterate over the keys inside config, split each key on 'x' and assign the resulting array as a value to "size" inside config[key].
Here is an N1QL query I tried (which obviously didn't work, hence this question here);
update AppBucket a set a.config[`size`].size = split(size, `x`) for size in OBJECT_NAMES(a.config) end
where meta(a).id like 'cnfg::40792';
Thanks in advance.
If you need to access the dynamic field you must use array brackets immediately after dot (map access) i.e config.[v] and v must be string or evaluate to string. It evaluates expression inside array brackets, it must be string, then converts into identifier and substitutes it and evaluate rest of the path. ex: config.["xyz"] ==> config.xyz , config.[f1] (f1 is "field1") ===> config.field1
Also split key must be string not identifier i.e. "x"
INSERT INTO default VALUES ("cnfg::40792", { "config": { "160x600": { "siteId": "123455677", "size":[160,600] }, "300x250": { "siteId": "123455677", "size" : [300,250] }, "300x600": { "siteId": "123455677", "size": [300,600] } } });
UPDATE default AS a USE KEYS "cnfg::40792"
SET a.config.[v].size = SPLIT(v, "x") FOR v IN OBJECT_NAMES(a.config) END;
The updated ARRAY will have strings i.e ["160","600"]. If you need numbers use the following command. If string can't convert to number it will converts to NULL.
UPDATE default AS a USE KEYS "cnfg::40792"
SET a.config.[v].size = ARRAY TO_NUMBER(v1) FOR v1 IN SPLIT(v, "x") END
FOR v IN OBJECT_NAMES(a.config) END;
Related
I have a json column with this format and How to modify element from postgres jsonb by key?
{
"Content": {
"CustomerInfo": {
},
"Identifier": null,
"Operating": {
"Identifier": "ABC-8585",
"TypeIdentifier": "VAL_OP",
"SaleIdentifier": "01000042"
},
},
}
How to remove "ABC-" from Identifier key?
Result In:
{
"Content": {
"CustomerInfo": {
},
"Identifier": null,
"Operating": {
"Identifier": "8585",
"TypeIdentifier": "VAL_OP",
"SaleIdentifier": "01000042"
},
},
}
Here is the query I apply to update a json value but it does not work.
update "tbleName" set "columnName" = replace('Content.Operating.Identifier','ABC-','')::jsonb ? 'Content.Operating.Identifier'
You can achieve this by using a combination of jsonb_set, regular JSON reading operators, and replace:
UPDATE "tbleName"
set "columnName" = jsonb_set(
"columnName"::jsonb,
'{Content,Operating,Identifier}',
replace(("columnName"::jsonb -> 'Content' -> 'Operating' -> 'Identifier')::text, 'ABC-', '')::jsonb
);
Here you compute the column's new value in the following way:
read the value of the desired nested JSON key
do the replacement
write back the result to the same nested JSON key in the original JSON structure
I have an input file:
{
"errands": [
{
"name": "broker-deregistrar",
"label": "Deregister and Purge Instances",
"impact_warning": null,
"pre_delete": true
},
{
"name": "delete-all-service-instances",
"label": "Delete All Service Instances",
"impact_warning": null,
"pre_delete": true
},
{
"name": "deregister-broker",
"label": "Deregister On-Demand Service Broker",
"impact_warning": null,
"pre_delete": true
}
]
}
I would like to reformat this to make the values of .name into a key with a fixed value like this:
{
"deploy_products": "all",
"errands": {
"product_1_guid": {
"run_pre_delete": {
"broker-deregistrar": true,
"delete-all-service-instances": true,
"deregister-broker": true
}
}
},
"ignore_warnings": true
}
I can subset the values I want with this filter:
.errands[].name
which gives me:
"broker-deregistrar"
"delete-all-service-instances"
"deregister-broker"
but I want to get the selected values into a new JSON as keys.
while this kind of works,
.errands=(.product_1_guid=(.run_pre_delete=(.xxx=true | .yyy=true | .zzz=true)))
the list of errand names is variable in that they have different names and counts. i.e. the list of errands may only be "delete-apps", or even nothing at all.
and in the above example I need .xxx, .yyy and .zzz to come from the original JSON.
Generate the name-true pairs within an array constructor so that you can easily merge them with add and place the result wherever it belongs.
{
deploy_products: "all",
errands: {
product_1_guid: {
run_pre_delete: [
{ (.errands[].name): true }
] | add
}
},
ignore_warnings: true
}
Online demo
{
"responseCode": "200",
"data": {
"sequence": 1,
"used": true,
"sensingTags": [
{
"code": "LED",
"value": 1,
"updatedOn": 1587557350251
}
]
}
}
My goal is get updatedOn value from this json using jsonPath like this
1587557350251
i thought below jsonPath will work but it extract only empty list.
$..sensingTags[?(#.code == 'LED')][0].updatedOn
And i want to know how to extract value like below
{
"code": "LED",
"value": 1,
"updatedOn": 1587557350251
}
Not like this one.
[
{
"code" : "LED",
"value" : 1,
"updatedOn" : 1587557350251
}
]
As per Getting a single value from a JSON object using JSONPath, JsonPath will always return an array (or a false) at that point...
Best you can do is process it as an array of updatedOn and simply always grab the first value.
$..sensingTags[?(#.code == 'LED')].updatedOn
I have an API gateway that scans a DynamoDB table. I want to pass LastEvaluatedKey in my request body; if I pass a LastEvaluatedKey then the everything works and I get a response with the expected data - so I'm half way there.
But, of course, the first time I send a request to the API LastEvaluatedKey will not exist, so the ExclusiveStartKey in the mapping template that expects a LastEvaluatedKey must be optional. I've tried a few different ways to get this to be optional but nothing has worked so far. Here is what I have:
#set($hasName = $input.json('$.Name'))
{
"TableName": "MyTable",
#if($hasName && $hasName.length() != 0)
"ExclusiveStartKey": {
"Name": {
"S": $input.json('$.Name')
},
"Date": {
"S": $input.json('$.Date')
}
},#end
"FilterExpression": "begins_with(#dt, :tdt)",
"ExpressionAttributeNames": {
"#dt": "Date"
},
"ExpressionAttributeValues": {
":tdt": {
"S": "$input.params('date')"
}
}
}
As I say, the above works when I do pass a LastEvaluatedKey in my request body, but when I do not I get the error:
{
"__type": "com.amazon.coral.validate#ValidationException",
"message": "The provided starting key is invalid: One or more parameter values were invalid: An AttributeValue may not contain an empty string"
}
...it's still expected the LastEvaluatedKey
I've also tried wrapping Name and Date inside if #if but with no luck at all. I've taken inspiration from other answers such as: this and this, but no luck.
In my example cursor is the LastEvaluatedKey:
#set($hasCursor = $input.params('cursor') != "")
{
"TableName": "my-table"
#if($hasCursor) "ExclusiveStartKey":$util.base64Decode("$input.params('cursor')")
#end
}
It just checks if cursor is passed as a query param (like /my/api?cursor=myencodedlastevaluatedkey), and only adds ExclusiveStartKey to the request if it is.
If you know beforehand that both keys are string type, you can do:
#set($Name = $input.params('Name'))
#set($Date = $input.params('Date'))
{
#if($Name != '' && $Date != '')
"ExclusiveStartKey": {
"Name": {
"S": "$Name"
},
"Date": {
"S": "$Date"
}
},
#end
#if($Date != '')
"FilterExpression": "begins_with(#dt, :tdt)",
"ExpressionAttributeNames": {
"#dt": "Date"
},
"ExpressionAttributeValues": {
":tdt": {
"S": "$Date"
}
}
},
#end
"TableName": "MyTable"
}
This makes the filter optional, only if Date is passed as argument
I'm after running into some trouble parsing a set of JSON documents using SQL Server 2017.
I've encountered a nested array (sample below) within a document which uses dynamic ObjectId's i.e. 123 as the object Key as opposed to using a static key i.e. Category and then having a separate key:value to ref the ObjectId.
As a result I can't extract the items to a table using the regular CROSS APPLY OPENJSON syntax without specifying each individual Object Id (there are thousands)?
Is there a way to do this without referencing each ObjectId explicitly ideally i'd like to return all product items in a table and just have a field withe the categoryId.
"ProductItems": {
"123": [
{
"item": "13663"
}
]
"124": [
{
"value": "2336"
},
{
"value": "3667"
}
],
"453": [
{
"value": "8667"
},
{
"value": "1956"
}
]
}
Try something like this:
DECLARE #x NVARCHAR(MAX)=
'{"ProductItems":{
"123": [
{
"item": "13663"
}
],
"124": [
{
"value": "2336"
},
{
"value": "3667"
}
],
"453": [
{
"value": "8667"
},
{
"value": "1956"
}
]
}}'
SELECT j2.*, j3.* FROM OPENJSON(#x) j1
CROSS APPLY OPENJSON(j1.Value) j2
CROSS APPLY OPENJSON(j2.Value) j3