Updating nested array n1ql - couchbase

The sample doc, I am trying to work with is:
{
"name": "level1",
"childLevel1": [
{
"name": "level2",
"childLevel2": [
{
"name": "level3",
"childLevel3": [
{
"name": "level4",
"attribute1": "data"
}
]
}
]
}
]
}
What we want to do is, with n1ql add one more array element to "childLevel3". I have tried the reference to https://developer.couchbase.com/documentation/server/4.5/n1ql/n1ql-language-reference/update.html
I was able to add a regular attribute to childLevel2 but after that it was not working. This is the query I have been trying out.
Update sample
set child2.childLevel3 = ARRAY_PUT(child2.childLevel3, {'attribute' : 'data2'})
FOR child2 in child1.childLevel2 when child2.name == "level3" END
for child1 in childLevel1 when childLevel1.name == 'level2' END
WHERE name == 'level1'
But it gives me error on parsing, I tried other ways too but nothing works.

Try
UPDATE sample
SET child2.childLevel3 = ARRAY_PUT(child2.childLevel3, {'attribute' : 'data2'})
FOR child2 in child1.childLevel2
FOR child1 in childLevel1
WHEN childLevel1.name == 'level2' AND child2.name == "level3"
END
WHERE name == 'level1';

I had to update an object within a nested array, recently in Couchbase. The answer above helped me to formulate this query in a bucket called "metadata". The data structure is:
{
"documentMetadata": {
"documentId": "42"
},
"results": [
{
"type": "FileStaging",
"status": "NOT STARTED"
}
],
"type": "runLog"
}
The query that worked for me:
UPDATE metadata
SET res.status = 'QUEUED'
FOR res in results
WHEN res.type = 'FileStaging'
END
WHERE type = 'runLog'
AND documentMetadata.documentId = '42'

Related

Removing nested pscustomobject within Azure Rule JSON

Been struggling with deleting a nested object within JSON returned from an Azure Alert Rule query.
Thanks to folks here, I've learned how to add a PSCustomObject within another. In this case, (below) to add a webhook action
"actions": [
{
"$type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleEmailAction, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendtoserviceowners": true,
"customEmails": [
"email2#domain.com",
"email1#domain.com"
]
}
]
$rule.properties.actions += [PSCustomObject]#{
'$type' = "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleWebhookAction, Microsoft.WindowsAzure.Management.Mon.Client";
'odata.type' = "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleWebhookAction";
serviceuri = "http://www.webhooktest.com"
}
Which results in
"actions": [
{
"$type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleWebhookAction, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleWebhookAction",
"serviceUri": "http://www.webhooktest.com"
},
{
"$type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleEmailAction, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": false,
"customEmails": [
"email2#domain.com",
"email1#domain.com"
]
}
]
I need to be able to remove the webhook and leave the email. If I could add it using +=, why does trying to remove it with -=
$rule.properties.actions -= [PSCustomObject]#{
'$type' = "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleWebhookAction, Microsoft.WindowsAzure.Management.Mon.Client";
'odata.type' = "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleWebhookAction";
serviceuri = "http://www.webhooktest.com"
}
result in
result in [System.Object[]] does not contain a method named 'op_Subtraction'
I've not had luck with the Remove() method either. What will work?

Asserting the values in JSON response through tests in Postman

My JSON response body looks like :
[
{
"_time": "1499996827804",
"properties": {
"length": "80",
"width": "4500"
}
}
]
I am using Postman to write tests to assert on value of length and width and _time.
I wrote :
var data = JSON.parse(responseBody);
tests["Check length value"] = data.length === "80";
But it's failing. Can anyone help ?
If your JSON looks like this:
[ { "_time": "1499996827804", "properties": { "length": "80", "width": "4500" } } ]
Then you need to fix the data.length === "80" part of your test.
Firstly, your JSON is an array, so you need to be selecting data[0] to get the first item in the response (which is { "_time": "1499996827804", "properties": { "length": "80", "width": "4500" } }). Then, it looks like you're trying to check the length part of the response, which is under the properties object. So your selector should now look like this: data[0].properties.
And finally, to access the length part, add .length to the end of your selector: data[0].properties.length.
Put it all together, and you should have:
tests["Check length value"] = data[0].properties.length === "80";
Hope it helps!
Your data is coming back in an array so you need to get the first item of the array. Also length is a sub property of the "properties" object. Try this:
tests["Check length value"] = data[0].properties.length === "80";

Insert into existing map a map structure in DynamoDB using Nodejs

Structure of an item in database is as shown below:
{
"cars": {
"x": [
{
"time": 1485700907669,
"value": 23
}
]
},
"date": 1483214400000,
"id":"1"
}
I have to add a new item "z" of type list to cars like
{
"cars": {
"x": [
{
"time": 1485700907669,
"value": 23
}
],
"z": [
{
"time": 1485700907669,
"value": 23
}
]
},
"date": 1483214400000,
"id": "1"
}
What would the update expression in Node.js look like if I want to achieve somethings like this?
So far this is what I came up with:
set #car.#model= list_append(if_not_exists(#car.#model, :empty_list), :value)
However, if the item does not exist at the time of creation it throws error. Any idea how to do this?
This is the updated parameter I am using, still doesn't work
var params = {
TableName:table,
Key:{
"id": id,
"date": time.getTime()
},
ReturnValues: 'ALL_NEW',
UpdateExpression: 'SET #car.#model = if_not_exists(#car.#model,
:empty_list)',
ExpressionAttributeNames: {
'#car': 'cars',
'#model':"z"
},
ExpressionAttributeValues: {
':empty_list': [],
}
};
The solution is to update operation in two steps, first create a empty map for the parent since it does not exist in the first place.
So, in my case
SET #car= :empty_map
where :empty_map = {}
after doing this run the other update expression
SET #car.#model = list_append(if_not_exists(#car.#model, :empty_list), :value)
where :empty_list=[] and :value= {
"time": 1485700907669,
"value": 23
}
Break your update expression apart into two separate expressions:
SET #car.#model = if_not_exists(#car.#model, :empty_list) SET #car.#model = list_append(#car.#model, :value)

Using JPath, how do I return a value based on another key value pair of the same node?

I have the following JSON file. It is truncated for brevity of this question. An actual JSON file would contain 10 - 20 messages and 3 - 15 results.
{
"messages": [
{
"type": "msgInfo",
"description": "Some stuff happened"
},
{
"type": "msgInfo",
"description": "More stuff happened"
},
{
"type": "msgInfo",
"description": "yup, more stuff happened"
}
],
"results": [
{
"parameterId": "val_1",
"dataType": "Double",
"value": 123.45
},
{
"parameterId": "val_2",
"dataType": "Double",
"value": 246.80
},
{
"parameterId": "val_3",
"dataType": "Double",
"value": 135.79
},
{
"parameterId": "val_4",
"dataType": "Long",
"value": 20161021
}
]
}
I'm trying to retrieve the value of the value key based on the value of the parameterId key. For example, I need to return "123.45" using a JPath to "val_1".
So far I have this code (copied from this post) but I can't get the path correct.
JObject obj = JObject.Parse(json);
JToken token = obj["results"]["parameterId"];
Console.WriteLine(token.Path + " -> " + token.ToString());
Console.ReadLine();
What do I need to do in order to return "123.45" using a JPath to "val_1"?
To get the value token from one of the results in the results array based on the value of the parameterId token, you need to use the SelectToken method with a JSONPath query expression:
JToken token = obj.SelectToken("$.results[?(#.parameterId=='val_1')].value");
JSONPath syntax can be a little tricky to get right sometimes, depending on what you're trying to do, so you might find an online expression evaluator such as this one helpful to experiment with.
Alternatively, you can use a LINQ query to do the same thing:
JToken token = obj["results"]
.Where(result => (string)result["parameterId"] == "val_1")
.Select(result => result["value"])
.FirstOrDefault();
Here is a fiddle showing both approaches: https://dotnetfiddle.net/8qiSCa

couchbase sort issue in java code

Below is the document on which I am working:
{
"id": "idgwSRWDUJjQH",
"rev": "15-13d1d4545cd601560000000000000000",
"expiration": 0,
"flags": 0
}
{
"geminiType": "storegroup",
"_class": "web.model.StoreGroup",
"order": "10",
"childId": [
],
"name": "aaa",
"parent": "root",
"userGroupId": [
],
"type": "Folder",
"storeId": [
]
}
I am trying to sort based on name as below
function (doc, meta) {
if(doc.geminiType == "storegroup") {
emit(doc.name, [ meta.id,doc.name, doc.parent, doc.type]);
}
}
This I have created permanent view in couchbase console. I am fetching the document from my jave code using couchbase client as below:
View storeGrpView = cc.getView(RRConsts.STORE_GROUP_VIEW_DESIGN_DOC, RRConsts.STORE_GROUP_VIEW);
Query getAllstoreGrpQuery = new Query();
getAllstoreGrpQuery.setIncludeDocs(true);
getAllstoreGrpQuery.setStale(Stale.FALSE);
ViewResponse result = cc.query(storeGrpView, getAllstoreGrpQuery);
logger.info("getAllstoreGrpQuery resultset: " + result.toString());
for(ViewRow row : result) {
logger.info("store group :"+row.getDocument().toString());
}
}
Here I am getting the result in order of meta.id of the doc but i was expecting the result set to be in order of doc.name. Please let me know where I am doing wrong.
I got the solution to above issue. Actually if I used below two get method instead of row.getDocument() to fetch data, I am getting data in sorted order as expected.
row.getkey()
row.getvalue()