Iteration through array data - ruby

I have a JSON data which in the following format:
[{
"id": 1,
"children": [{
"id": 7,
"children": [{
"id": 8,
"children": [{
"id": 4
}, {
"id": 5
}, {
"id": 11
}
]
}, {
"id": 9
}
]
}, {
"id": 6
}, {
"id": 10
}
]
}, {
"id": 2,
"children": [{
"id": 3
}, {
"id": 12
}
]
}, {
"id": 13
}
]
The tree for this JSON data is:
I want to loop through all the nodes and extract the "id" of all data maintaining its parent child hierarchy. How can i do this using recursive function.
The idea is to parse the json structure in ruby.

I just coded a node js code, you can still make it work on a browser in js, but you will need to download the underscore library here.
_und = require('underscore');
data = [{
"id": 1,
"children": [{
"id": 7,
"children": [{
"id": 8,
"children": [{
"id": 4
}, {
"id": 5
}, {
"id": 11
}
]
}, {
"id": 9
}
]
}, {
"id": 6
}, {
"id": 10
}
]
}, {
"id": 2,
"children": [{
"id": 3
}, {
"id": 12
}
]
}, {
"id": 13
}
]
function parse_tree_2(n) {
return(_und.map(n, parse_tree));
}
function parse_tree(n) {
if (n['children']) {
return({id: n['id'], children: parse_tree_2(n['children'])});
} else {
return({id: n['id']});
}
}
result = _und.map(data, parse_tree);
console.log("Result: %j", result);
You can put that into a file, and execute it with node (by download underscore with nmp install node).
On plain js it would be something like:
<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/javascript">
data = [{
"id": 1,
"children": [{
"id": 7,
"children": [{
"id": 8,
"children": [{
"id": 4
}, {
"id": 5
}, {
"id": 11
}
]
}, {
"id": 9
}
]
}, {
"id": 6
}, {
"id": 10
}
]
}, {
"id": 2,
"children": [{
"id": 3
}, {
"id": 12
}
]
}, {
"id": 13
}
]
function parse_tree_2(n) {
return(_.map(n, parse_tree));
}
function parse_tree(n) {
if (n['children']) {
return({id: n['id'], children: parse_tree_2(n['children'])});
} else {
return({id: n['id']});
}
}
result = _.map(data, parse_tree);
console.log("Result: %j", result);
</script>
Ruby code:
require 'json'
data = <<EOF
[{
"id": 1,
"children": [{
"id": 7,
"children": [{
"id": 8,
"children": [{
"id": 4
}, {
"id": 5
}, {
"id": 11
}
]
}, {
"id": 9
}
]
}, {
"id": 6
}, {
"id": 10
}
]
}, {
"id": 2,
"children": [{
"id": 3
}, {
"id": 12
}
]
}, {
"id": 13
}
]
EOF
json = JSON.parse(data)
def parse_tree(n)
if n["children"]
{id: n["id"], children: n['children'].map {|c| parse_tree(c)} }
else
{id: n["id"]}
end
end
result = json.map {|n| parse_tree(n) }
puts result

Related

How to filter out only entries of an embedded list with elastic search?

I want to filter out only entries from a list "NestedRecords" inside each "Record" entry.
Let's say I have these Id's of nested records which should be returned:
nestedRecordsToBeReturned = [1,3]
This is the given table with records and nestedRecords inside each record:
{
"Records": [
{
"Record": "record1",
"NestedRecords": [
{
"id": 1,
"label": "l1"
},
{
"id": 2,
"label": "l2"
},
{
"id": 3,
"label": "l3"
},
{
"id": 4,
"label": "l4"
},
{
"id": 6,
"label": "l6"
}
]
},
{
"Record": "record2",
"Records": [
{
"id": 1,
"label": "l1"
},
{
"id": 2,
"label": "l2"
},
{
"id": 4,
"label": "l4"
},
{
"id": 7,
"label": "l7"
}
]
},
{
"Record": "record3",
"Records": [
{
"id": 2,
"label": "l2"
},
{
"id": 3,
"label": "l3"
},
{
"id": 9,
"label": "l9"
},
{
"id": 10,
"label": "l10"
}
]
}
]
}
This is what I want to be returned:
{
"Records": [
{
"Record": "record1",
"NestedRecords": [
{
"id": 1,
"label": "l1"
},
{
"id": 3,
"label": "l3"
},
]
},
{
"Record": "record2",
"Records": [
{
"id": 1,
"label": "l1"
},
]
},
{
"Record": "record3",
"Records": [
{
"id": 3,
"label": "l3"
},
]
}
]
}
How do I achieve this with an elastic query?
Is it even possible to filter a list which is embedded in a document?

How to groupBy the collection of Laravel with the nested field of type array?

I have this collection, and I want to change this data in order that the key will be the branches id and the value will be the items:
{
"data": [
{
"id": 5020,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
{
"id": 6,
"title": "vegetable",
},
},
{
"id": 5025,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
}
]
}
I want to group by this data by branches -> id , something like this:
{
"data": [
"7" : [
{
"id": 5020,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
{
"id": 6,
"title": "vegetable",
},
},
{
"id": 5025,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
]
}
],
"6" : [
{
"id": 5020,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
{
"id": 6,
"title": "vegetable",
},
},
],
}
How can I use the group By method of collection in Laravel? I want to have data like this and my data is the type of collection
You can use a callback in groupBy method to provide custom logic.
Example:
collect($data)->groupBy(fn($item, $key) => $item['branches'][0]['id']);
But in this example I want to suggest you to use loop:
$myGroups = [];
foreach($data as $item) {
foreach($item['branches'] as $branch) {
$myGroups[$branch['id']][] = $item;
}
}

How to use filter in map

I have following code:
%dw 2.0 output application/json var attributeIdMapping =
${vault::attributeIdMapping}
--- {
"objectTypeId": 3,
"attributes": vars.requestBody mapObject (value, key) ->
{
"objectTypeAttributeId": (attributeIdMapping.attributes filter ($.name == key))[0].id,
"objectAttributeValues": [{
"value": value,
"key": key
}]
} }
attributeIdMapping:
{
"attributes": [
{
"name": "accountType",
"id": "87"
},
{
"name": "accountClass",
"id": "89"
},
{
"name": "accountName",
"id": "85"
},
{
"name": "displayName",
"id": "18"
},
{
"name": "accountCategory",
"id": "88"
},
{
"name": "accountNumber",
"id": "84"
},
{
"name": "description",
"id": "86"
},
{
"name": "accountGroup",
"id": "90"
}
]
}
vars.requestBody:
{
"displayName": "TestMulesoft2",
"description": "Test"
}
But my filter shows null in the end. As I understand key is not passed to level below map itself. How can I get this working?
I put all the input data inside the script to simplify reproduction. The problem seems to be using the operator == to compare a string and a key types returns empty. Using the operator ~= which attempts to coerce appears to return the expected result:
%dw 2.0
output application/json
var attributeIdMapping =
{
"attributes": [
{
"name": "accountType",
"id": "87"
},
{
"name": "accountClass",
"id": "89"
},
{
"name": "accountName",
"id": "85"
},
{
"name": "displayName",
"id": "18"
},
{
"name": "accountCategory",
"id": "88"
},
{
"name": "accountNumber",
"id": "84"
},
{
"name": "description",
"id": "86"
},
{
"name": "accountGroup",
"id": "90"
}
]
}
var requestBody = {
"displayName": "TestMulesoft2",
"description": "Test"
}
--- {
"objectTypeId": 3,
"attributes": requestBody mapObject (value, key) ->
{
"objectTypeAttributeId": (attributeIdMapping.attributes filter ($.name ~= key))[0].id,
"objectAttributeValues": [{
"value": value,
"key": key
}]
} }
Output:
{
"objectTypeId": 3,
"attributes": {
"objectTypeAttributeId": "18",
"objectAttributeValues": [
{
"value": "TestMulesoft2",
"key": "displayName"
}
],
"objectTypeAttributeId": "86",
"objectAttributeValues": [
{
"value": "Test",
"key": "description"
}
]
}
}

Error when saving composites id inside a for loop

I am trying to persist some objects that have a composite id. If I am only sending an array with one element it works fine, but it the array has more than one it throws an exception when saving the first one. public boolean
addParamsToChart(List<ChartParams> chartParams, Long chartId) {
List<ChartParams> chartParamsList = new ArrayList<>();
for(ChartParams chartParam: chartParams) {
ChartParamsId id = new ChartParamsId();
// id.setChartId(chartId);
id.setChartId(chartParam.getChart().getId());
id.setParamId(chartParam.getParam().getId());
id.setContextSourceId(chartParam.getContextSource().getId());
chartParam.setChartParamsId(id);
if(chartParamsRepository.save(chartParams) !=null) {
chartParamsList.add(chartParam);
}
}
if(chartParamsList.size()!=chartParams.size()) {
// something went wrong, delete previous inserted
deleteChartParams(chartParamsList);
chartRepository.delete(chartId);
return false;
}
return true;
}
[{
"chart": {
"id": 49,
"cv": {
"id": 1,
"name": "Money",
"category": {
"id": 1,
"name": "Euros"
},
"definition": "\"European curreny.\" [EU:euro]",
"enabled": true,
"cvid": "CC:1010"
},
"accountType": {
"id": 1,
"name": "saving"
},
"name": "Euro saving charts"
},
"param": {
"id": 8,
"name": "Totals",
"isFor": "Currency"
},
"contextSource": {
"id": 3,
"name": "euro",
"internal": "eu",
"abbreviatedName": "eu"
} }]
But for this having two objects inside instead of one is not working, throwing an exception at the first save.
[{
"chart": {
"id": 52,
"cv": {
"id": 55,
"name": "Stocks",
"category": {
"id": 1,
"name": "Stocks"
},
"definition": "\"General stocks.\" [GS:ST]",
"enabled": true,
"cvid": "ST:0111"
},
"accountType": {
"id": 1,
"name": "saving"
},
"name": "Stock saving chart"
},
"param": {
"id": 8,
"name": "Totals",
"isFor": "Currency"
},
"contextSource": {
"id": 6,
"name": "stock",
"internal": "st",
"abbreviatedName": "st"
} }, {
"chart": {
"id": 52,
"cv": {
"id": 55,
"name": "Stocks",
"category": {
"id": 1,
"name": "Stocks"
},
"definition": "\"General stocks.\" [GS:ST]",
"enabled": true,
"cvid": "ST:0111"
},
"accountType": {
"id": 1,
"name": "saving"
},
"name": "Stock saving chart"
},
"param": {
"id": 8,
"name": "Totals",
"isFor": "Currency"
},
"contextSource": {
"id": 7,
"name": "Sold stock",
"internal": "st_sold",
"abbreviatedSequence": "st_sold"
} }]
The exception I got is:
org.hibernate.id.IdentifierGenerationException: null id generated for:class eu.stocks.chart.chartParams.ChartParams

Getting full documents using ElasticSearch aggregations

I've got an index like:
[
{
"Name": "Alex",
"LastName": "Ich",
"Department": 2
},
{
"Name": "Charlie",
"LastName": "Sheen",
"Department": 3
},
{
"Name": "Peter",
"LastName": "Petrelli",
"Department": 5
},
{
"Name": "Alan",
"LastName": "Harper",
"Department": 6
},
{
"Name": "Ann",
"LastName": "Bottle",
"Department": 3
},
]
And I want to get the results with distinct Department, I don't care about order, just 1 result per Department. I tried with aggregations but I could only manage to get the different Deppartments with the doc_count associated. They query I tried is something like:
{
"aggs": {
"deppartments": {
"terms": {
"field": "Department"
}
}
},"size": 0
}
It returns:
"buckets": [
{
"key": 2,
"doc_count": 1
},
{
"key": 3,
"doc_count": 2
},
{
"key": 5,
"doc_count": 1
},
{
"key": 6,
"doc_count": 1
},
]
When I want something like:
[
{
"Name": "Alex",
"LastName": "Ich",
"Department": 2
},
{
"Name": "Charlie",
"LastName": "Sheen",
"Department": 3
},
{
"Name": "Peter",
"LastName": "Petrelli",
"Department": 5
},
{
"Name": "Alan",
"LastName": "Harper",
"Department": 6
}
]
You can use Top hits aggregation for this
{
"aggs": {
"departments": {
"terms": {
"field": "Department",
"size": 10
},
"aggs": {
"search_results": {
"top_hits": {
"size": 10 <--- you can change the size to 1 if you want
}
}
}
}
},
"size": 0
}
Does this help?

Resources