Grouping dynamic JSON Keys using map and reduce if possible javascript - javascript

I want to group Dynamic Object keys of a json. The object values from each keys will be group to their respective key.
I tried using map and reduce to group it but the results are not grouped as I expected.
Here is my JSON Object
var data = [
{
"type": 6,
"data": {
"error": {
"cause": {
"root": {
"Extracted": {
"Body": {
"Error": {
"ErrorCode": "143",
"ErrorString": "NotFound",
"info": {
"Error": {
"errorDesc": "Data Not Found",
"subs": {
"attrib": {
"subs_name": "123com",
"subs_no": 4
}
}
}
}
}
}
}
}
}
}
},
"status": true
},
{
"type": 6,
"data": {
"error": {
"cause": {
"root": {
"Extracted": {
"Body": {
"Error": {
"ErrorCode": "143",
"ErrorString": "NotFound",
"info": {
"Error": {
"errorDesc": "Company Not Found",
"subs": {
"attrib": {
"subs_name": "QRS",
"subs_no": 4
}
}
}
}
}
}
}
}
}
}
},
"status": true
},
{
"type": 6,
"data": {
"error": {
"cause": {
"root": {
"Extracted": {
"Body": {
"Error": {
"ErrorCode": "123",
"ErrorString": "SystemFailure",
"info": {
"Error": {
"errorDesc": "Internal server error",
"subs": {
"attrib": {
"subs_name": "ABC",
"subs_no": 2
}
}
}
}
}
}
}
}
}
}
},
"status": true
},
{
"type": 6,
"data": {
"error": {
"cause": {
"root": {
"Extracted": {
"Body": {
"Error": {
"ErrorCode": "123",
"ErrorString": "SystemFailure",
"info": {
"Error": {
"errorDesc": "Insufficient Data",
"subs": {
"attrib": {
"subs_name": "DEF",
"subs_no": 3
}
}
}
}
}
}
}
}
}
}
},
"status": true
},
{
"type": 6,
"data": {
"error": {
"cause": {
"root": {
"Extracted": {
"Body": {
"Error": {
"ErrorCode": "999",
"ErrorString": "Unknown",
"info": {
"Unknown": {
"desc": "UnknownError",
"subs": "GHI"
}
}
}
}
}
}
}
}
}
},
"status": true
}
]
This is the code that I have tried but didn't get the result I want
var x = data.map((e) => {
var el = {}
el[e.data.error.cause.root.Extracted.Body.Error.ErrorString] =
[e.data.error.cause.root.Extracted.Body.Error.info];
return el;
})
console.log(x);
The result I got:
[
{
"NotFound": {....}
},
{
"NotFound": {....}
},
{
"SystemFailure": {....}
},
{
"SystemFailure": {....}
},
{
"Unknown": {....}
},
]
The result I expect:
[
{
"NotFound": [
{
"Error": {
"errorDesc": "Data Not Found",
"subs": {
"attrib": {
"subs_name": "123com",
"subs_no": 4
}
}
},
{
"Error": {
"errorDesc": "Company Not Found",
"subs": {
"attrib": {
"subs_name": "QRS",
"subs_no": 4
}
}
}
}
]
},
{
"SystemFailure": [
{
"Error": {
"errorDesc": "Internal server error",
"subs": {
"attrib": {
"subs_name": "ABC",
"subs_no": 2
}
}
},
{
"Error": {
"errorDesc": "Insufficient Data",
"subs": {
"attrib": {
"subs_name": "DEF",
"subs_no": 3
}
}
}
]
},
{
"Unknown": [
{
"Unknown": {
"desc": "UnknownError",
"subs": "GHI"
}
}
]
}
]

You could reduce the array. Create an accumulator object with unique ErrorString as key. Set the value to be an object with the same ErrorString as key. Then add each info object based on the ErrorString. Use Object.values() get the grouped values as an array
const data=[{type:6,data:{error:{cause:{root:{Extracted:{Body:{Error:{ErrorCode:"143",ErrorString:"NotFound",info:{Error:{errorDesc:"Data Not Found",subs:{attrib:{subs_name:"123com",subs_no:4}}}}}}}}}}},status:true},{type:6,data:{error:{cause:{root:{Extracted:{Body:{Error:{ErrorCode:"143",ErrorString:"NotFound",info:{Error:{errorDesc:"Company Not Found",subs:{attrib:{subs_name:"QRS",subs_no:4}}}}}}}}}}},status:true},{type:6,data:{error:{cause:{root:{Extracted:{Body:{Error:{ErrorCode:"123",ErrorString:"SystemFailure",info:{Error:{errorDesc:"Internal server error",subs:{attrib:{subs_name:"ABC",subs_no:2}}}}}}}}}}},status:true},{type:6,data:{error:{cause:{root:{Extracted:{Body:{Error:{ErrorCode:"123",ErrorString:"SystemFailure",info:{Error:{errorDesc:"Insufficient Data",subs:{attrib:{subs_name:"DEF",subs_no:3}}}}}}}}}}},status:true},{type:6,data:{error:{cause:{root:{Extracted:{Body:{Error:{ErrorCode:"999",ErrorString:"Unknown",info:{Unknown:{desc:"UnknownError",subs:"GHI"}}}}}}}}},status:true}];
const merged = data.reduce((acc, o) => {
const e = o.data.error.cause.root.Extracted.Body.Error;
acc[e.ErrorString] = acc[e.ErrorString] || { [e.ErrorString]: [] };
acc[e.ErrorString][e.ErrorString].push(e.info)
return acc;
}, {})
const output = Object.values(merged);
console.log(output)

Related

How to retrieve and process the data from the open dialog form?

I'm trying to process the response data in the open dialog but got stuck in this the retrieval.
I followed the step by step procedure given in this link: https://developers.google.com/chat/how-tos/dialogs but unfortunately, it didn't work as well.
Here is the sample code:
My goal is to get the data from the dialog form then process it. My pain point is in the code: event.common.formInputs.firstnumber.stringInputs.value[0] where it returns undefined reading value.
function openDialog(event) {
return {
"action_response": {
"type": "DIALOG",
"dialog_action": {
"dialog": {
"body": {
"sections": [
{
"header": "Addition Calculator:",
"widgets": [
{
"textInput": {
"label": "First Number",
"type": "SINGLE_LINE",
"name": "firstnumber"
}
},
{
"textInput": {
"label": "Second Number",
"type": "SINGLE_LINE",
"name": "secondnumber"
}
},
{
"textInput": {
"label": "Third Number",
"type": "SINGLE_LINE",
"name": "thirdnumber"
}
},
{
"buttonList": {
"buttons": [
{
"text": "Submit",
"onClick": {
"action": {
"function": "giveAnswer"
}
}
}
]
},
"horizontalAlignment": "END"
}
]
}
]
}
}
}
}
};
}
function giveAnswer(event) {
var firstterm = parseFloat(event.common.formInputs.firstnumber.stringInputs.value[0])
var secondterm = parseFloat(event.common.formInputs.secondnumber.stringInputs.value[0])
var thirdterm = parseFloat(event.common.formInputs.thirdnumber.stringInputs.value[0])
var sum = firstterm+secondterm+thirdterm
return {
"cardsV2": [{
"cardId": "addContact",
"card": {
"header": {
"title": "The SUM is:",
"subtitle": "Answer",
"imageUrl": "https://images.emojiterra.com/google/noto-emoji/v2.034/128px/1f4f1.png",
"imageType": "SQUARE"
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": sum
}
}
]
}
]
}
}
]
}
}
I tried the example in here but didn't work as well. https://developers.google.com/chat/how-tos/dialogs#receive_form_data_from_dialogs

Match multiple items inside a nested array - Elasticsearch

I've stored documents within my elasticsearch service that are similar to this:
[
{
"first_name": "John",
"last_name": 'Dow',
"statuses": [
{
"name": "STAT1",
"start_date":"2022-10-21T21:03:06",
"happy": false
},
{
"name": "STAT2",
"start_date":"2022-10-21T21:03:06",
"happy": true
},
]
}
...
]
I've a component within my UI where the user can select the required filters that he wants to apply on the data.
For example give me the docs where:
first_name == "John" & last_name== 'Doe'
After the user selecting the desired filters, i'm creating a query similar to this one:
"query": {
"bool": {
"must": [
{
"regexp": {
"first_name": {
"value": ".*John.*"
}
},
"regexp": {
"last_name": {
"value": ".*Doe.*"
}
},
}
],
"should": []
}
}
Now I've a new requirement where i need to allow to filter the documents as follow:
Show me the document where:
statuses.name === STAT1 & statuses.happy === false
and
statuses.name === STAT2 & statuses.happy === true
and
first_name === Jhon
I didn't found any example how to achieve that requirement, any help would be appreciated
You can start with this query. Read more about nested queries.
{
"query": {
"bool": {
"must": [
{
"match": {
"first_name": "john"
}
}
],
"filter": [
{
"nested": {
"path": "statuses",
"query": {
"bool": {
"must": [
{
"match": {
"statuses.name": "STAT1"
}
},
{
"term": {
"statuses.happy": {
"value": "false"
}
}
}
]
}
}
}
},
{
"nested": {
"path": "statuses",
"query": {
"bool": {
"must": [
{
"match": {
"statuses.name": "STAT2"
}
},
{
"term": {
"statuses.happy": {
"value": "true"
}
}
}
]
}
}
}
}
]
}
}
}

AWS Lambda Athena getQueryResults With no results

I'm trying to get the output of getQueryResults using the below code:
var AWS = require('aws-sdk');
var athena = new AWS.Athena();
const DEBUG = process.env.DEBUG;
const GLOCA_ENVID = process.env.GLOCA_ENVID;
const GLOCA_AWS_ACCOUNTID = process.env.GLOCA_AWS_ACCOUNTID;
const GLOCA_AWS_REGION = process.env.GLOCA_AWS_REGION;
exports.handler = function(event, context, callback) {
athena.getQueryResults({
QueryExecutionId: "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
},function(err,data){
if (err) console.log(err);
else {
console.log("Body: ", data);
}
});
}
Below is the output:
{
UpdateCount: 0,
ResultSet: { Rows: [ [Object] ], ResultSetMetadata: { ColumnInfo: [Array] } }
}
The output should look something like this:
{
"ResultSet": {
"Rows": [
{
"Data": [
{
"VarCharValue": "date"
},
{
"VarCharValue": "location"
},
{
"VarCharValue": "browser"
},
{
"VarCharValue": "uri"
},
{
"VarCharValue": "status"
}
]
},
{
"Data": [
{
"VarCharValue": "2014-07-05"
},
{
"VarCharValue": "SFO4"
},
{
"VarCharValue": "Safari"
},
{
"VarCharValue": "/test-image-2.jpeg"
},
{
"VarCharValue": "200"
}
]
},
{
"Data": [
{
"VarCharValue": "2014-07-05"
},
{
"VarCharValue": "SFO4"
},
{
"VarCharValue": "IE"
},
{
"VarCharValue": "/test-image-2.jpeg"
},
{
"VarCharValue": "200"
}
]
}
],
"ResultSetMetadata": {
"ColumnInfo": [
{
"CatalogName": "hive",
"SchemaName": "",
"TableName": "",
"Name": "date",
"Label": "date",
"Type": "date",
"Precision": 0,
"Scale": 0,
"Nullable": "UNKNOWN",
"CaseSensitive": false
},
{
"CatalogName": "hive",
"SchemaName": "",
"TableName": "",
"Name": "location",
"Label": "location",
"Type": "varchar",
"Precision": 2147483647,
"Data": [
"Scale": 0,
"Nullable": "UNKNOWN",
"CaseSensitive": true
},
{
"CatalogName": "hive",
"SchemaName": "",
"TableName": "",
"Name": "browser",
"Label": "browser",
"Type": "varchar",
"Precision": 2147483647,
"Scale": 0,
"Nullable": "UNKNOWN",
"CaseSensitive": true
}
]
}
},
"UpdateCount": 0
}
The above output is an example output, but a similar outcome is what I'm expecting. When I run in AWS CLI:
aws athena --region "us-west-2" get-query-results --query-execution-id a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
I get the expected output, so I'm unable to understand why I can't get the same result via lambda.
Thank you so much for all the help! :)
It actually looks like the code is fine. Looking at the response is shows that there is an Object within the ResultSet.Rows. Try to stringify the result before logging such that the handler looks like this:
exports.handler = function(event, context, callback) {
athena.getQueryResults({
QueryExecutionId: "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
},function(err,data){
if (err) console.log(err);
else {
console.log("Body: ", JSON.stringify(data, null, 2));
}
});
}

Try to query and aggregate in ElasticSearch but aggregrating not working - elasticsearch.js client

I'm trying to query my dataset for two purposes:
Match a term (resellable = true)
Order the results by their price
lowest to highest
Data set/doc is:
"data" : {
"resellable" : true,
"startingPrice" : 0,
"id" : "4emEe_r_x5DRCc5",
"buyNowPrice" : 0.006493, //Changes per object
"sub_title" : "test 1",
"title" : "test 1",
"category" : "Education",
}
//THREE OBJECTS WITH THE VALUES OF 0.006, 0.7, 1.05 FOR BUYNOWPRICE
I have three objects of these with different buyNowPrice
Query with agg is:
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"from": 0,
"size": 5,
"aggs": {
"lowestPrice": {
"terms": {
"field": "data.buyNowPrice",
"order": {
"lowest_price": "desc"
}
},
"aggs": {
"lowest_price": {
"min": {
"field": "data.buyNowPrice"
}
},
"lowest_price_top_hits": {
"top_hits": {
"size": 5,
"sort": [
{
"data.buyNowPrice": {
"order": "desc"
}
}
]
}
}
}
}
}
}
The query works fine, and the results are 3 objects that have resellable = true
The issue is, the agg is not organizing the results based off the lowest buy now price.
Each result, the order of buyNowPrice is: 1.06, 0.006, 0.7 - which is not ordered properly.
Switching to desc has no affect, so I don't believe the agg is running at all?
EDIT:
Using the suggestion below my query now looks like:
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"from": 0,
"size": 5,
"aggs": {
"lowestPrice": {
"terms": {
"field": "data.buyNowPrice",
"order": {
"lowest_price": "asc"
}
},
"aggs": {
"lowest_price": {
"min": {
"field": "data.buyNowPrice"
}
},
"lowest_price_top_hits": {
"top_hits": {
"size": 5
}
}
}
}
}
}
With the results of the query being:
total: { value: 3, relation: 'eq' },
max_score: 0.2876821,
hits: [
{
_index: 'education',
_type: 'listing',
_id: '4emEe_r_x5DRCc5', <--- buyNowPrice of 0.006
_score: 0.2876821,
_source: [Object]
},
{
_index: 'education',
_type: 'listing',
_id: '4ee_r_x5DRCc5', <--- buyNowPrice of 1.006
_score: 0.18232156,
_source: [Object]
},
{
_index: 'education',
_type: 'listing',
_id: '4444_r_x5DRCc5', <--- buyNowPrice of 0.7
_score: 0.18232156,
_source: [Object]
}
]
}
EDIT 2:
Removing the query for resellable = true the aggregation will sort properly and return the items in the proper order. But with the query for resellable included, it does not.
I'm assuming this has to do with the _score property overriding the sorting from agg? How would this be fixed
You can use a bucket sort aggregation that is a parent pipeline
aggregation which sorts the buckets of its parent multi-bucket
aggregation. Zero or more sort fields may be specified together with
the corresponding sort order.
Adding a working example (using the same index data as given in the question), search query, and search result
Search Query:
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"from": 0,
"size": 5,
"aggs": {
"source": {
"terms": {
"field": "data.buyNowPrice"
},
"aggs": {
"latest": {
"top_hits": {
"_source": {
"includes": [
"data.buyNowPrice",
"data.id"
]
}
}
},
"highest_price": {
"max": {
"field": "data.buyNowPrice"
}
},
"bucket_sort_order": {
"bucket_sort": {
"sort": {
"highest_price": {
"order": "desc"
}
}
}
}
}
}
}
}
Search Result:
"buckets": [
{
"key": 1.0499999523162842,
"doc_count": 1,
"highest_price": {
"value": 1.0499999523162842
},
"latest": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.08701137,
"hits": [
{
"_index": "stof_64364468",
"_type": "_doc",
"_id": "3",
"_score": 0.08701137,
"_source": {
"data": {
"id": "4emEe_r_x5DRCc5",
"buyNowPrice": 1.05 <-- note this
}
}
}
]
}
}
},
{
"key": 0.699999988079071,
"doc_count": 1,
"highest_price": {
"value": 0.699999988079071
},
"latest": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.08701137,
"hits": [
{
"_index": "stof_64364468",
"_type": "_doc",
"_id": "2",
"_score": 0.08701137,
"_source": {
"data": {
"id": "4emEe_r_x5DRCc5",
"buyNowPrice": 0.7 <-- note this
}
}
}
]
}
}
},
{
"key": 0.006000000052154064,
"doc_count": 1,
"highest_price": {
"value": 0.006000000052154064
},
"latest": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.08701137,
"hits": [
{
"_index": "stof_64364468",
"_type": "_doc",
"_id": "1",
"_score": 0.08701137,
"_source": {
"data": {
"id": "4emEe_r_x5DRCc5",
"buyNowPrice": 0.006 <-- note this
}
}
}
]
}
}
}
]
Update 1:
If you modify your search query as :
{
"query": {
"bool": {
"must": [
{
"term": {
"data.resellable": true
}
}
]
}
},
"aggs": {
"lowestPrice": {
"terms": {
"field": "data.buyNowPrice",
"order": {
"lowest_price": "asc" <-- change the order here
}
},
"aggs": {
"lowest_price": {
"min": {
"field": "data.buyNowPrice"
}
},
"lowest_price_top_hits": {
"top_hits": {
"size": 5
}
}
}
}
}
}
Running the above search query also, you will get your required results.

Fetch only specific objects from JSON via javascript or jQuery

I would like to fetch only specific objects from the below JSON such as only those JSON objects which have a classDefinition = "com.sap.bpm.wfs.UserTask". Please suggest on how to do this:
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
"id": "startevent1",
"name": "StartEvent1"
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
"id": "endevent1",
"name": "EndEvent1"
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
"id": "sequenceflow1",
"name": "SequenceFlow1",
"sourceRef": "83eaead8-cfae-459b-9bdd-8b12e32d6715",
"targetRef": "6c2b0935-444b-4299-ac8e-92973ce93558"
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
"symbols": {
"760f0725-3400-4d48-b082-5c69ad79d697": {},
"aa9a0d10-63be-4af8-9ac2-4d2b648a18fc": {},
"7fbd11bb-cf82-4a27-97d7-e80dda2014ee": {},
"20c66c48-6058-465e-b500-d69d6e54c028": {},
"2e8f324c-5361-4512-a09a-fc7693f206ba": {}
}
}
}
};
First, metadata.contents property should rather be an array.
If you really cannot change it to an array, then use Object.keys(metadata.contents)
For example:
Object.keys(metadata.contents)
.map(x => metadata.contents[x])
.filter(x => x.classDefinition == 'com.sap.bpm.wfs.UserTask')
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
}
}
}
var filtered = Object.keys(metadata.contents)
.map(x => metadata.contents[x])
.filter(x => x.classDefinition == 'com.sap.bpm.wfs.UserTask')
console.log(filtered)
A simple for loop can be used to get the desired fields:
var temp = [];
for (var index in metadata.contents) {
if (metadata.contents[index].classDefinition == "com.sap.bpm.wfs.UserTask") {
temp.push(metadata.contents[index]);
}
}
Or you can do one by one
var metadata = {
"contents": {
"83eaead8-cfae-459b-9bdd-8b12e32d6715": {
"classDefinition": "com.sap.bpm.wfs.StartEvent",
"id": "startevent1",
"name": "StartEvent1"
},
"13583ac9-596d-4375-b9e1-e5f6f21e829f": {
"classDefinition": "com.sap.bpm.wfs.EndEvent",
"id": "endevent1",
"name": "EndEvent1"
},
"6c2b0935-444b-4299-ac8e-92973ce93558": {
"classDefinition": "com.sap.bpm.wfs.UserTask",
"subject": "Upload document",
"description": "{context.description}",
"priority": "MEDIUM",
"isHiddenInLogForParticipant": false,
"userInterface": "sapui5://html5apps/saptest/com.sap.test",
"recipientUsers": "I311520, I310811",
"id": "usertask1",
"name": "UserTask1"
},
"6728bf81-3d4e-4ae3-a428-1700a2096d34": {
"classDefinition": "com.sap.bpm.wfs.SequenceFlow",
"id": "sequenceflow1",
"name": "SequenceFlow1",
"sourceRef": "83eaead8-cfae-459b-9bdd-8b12e32d6715",
"targetRef": "6c2b0935-444b-4299-ac8e-92973ce93558"
},
"aa99931e-2523-44c3-86b3-d522acdbde10": {
"classDefinition": "com.sap.bpm.wfs.ui.Diagram",
"symbols": {
"760f0725-3400-4d48-b082-5c69ad79d697": {},
"aa9a0d10-63be-4af8-9ac2-4d2b648a18fc": {},
"7fbd11bb-cf82-4a27-97d7-e80dda2014ee": {},
"20c66c48-6058-465e-b500-d69d6e54c028": {},
"2e8f324c-5361-4512-a09a-fc7693f206ba": {}
}
}
}
}
var content = metadata["contents"];
var subContent = content["6c2b0935-444b-4299-ac8e-92973ce93558"];
var classDef = subContent["classDefinition"];
alert(classDef);

Categories