RamdaJS groupBy and tranform object - ramda.js

I want to transform this array of objects using RamdaJS. From this array of objects
let children = [
{ "name": "Bob", "age": 8, "father": "Mike" },
{ "name": "David", "age": 10, "father": "Mike" },
{ "name": "Amy", "age": 2, "father": "Mike" },
{ "name": "Jeff", "age": 11, "father": "Jack" }
]
into this array of objects
let fatherAndKids = [
{
"father": "Mike",
"count" : 3,
"kids": [
{ "name": "Bob", "age": 8 },
{ "name": "David", "age": 10 },
{ "name": "Amy", "age": 2
}
]
},
{
"father": "Jack",
"count" : 1,
"kids": [
{ "name": "Jeff", "age": 11 }
]
}
]
Here's what i did so far. But i failed to remove the father keys from kids's array
R.pipe(
R.groupBy(R.prop('father')),
R.map(kids => ({
father: R.head(kids)["father"],
count: kids.length,
kids: kids
})),
R.values()
)(children)

Use R.applySpec to create the object, and use R.map with R.dissoc to remove the 'father' property:
const { pipe, groupBy, prop, applySpec, head, length, map, dissoc, values } = R
const fn = pipe(
groupBy(prop('father')),
map(applySpec({
father: pipe(head, prop('father')),
count: length,
kids: map(dissoc('father'))
})),
values
)
const children = [
{ "name": "Bob", "age": 8, "father": "Mike" },
{ "name": "David", "age": 10, "father": "Mike" },
{ "name": "Amy", "age": 2, "father": "Mike" },
{ "name": "Jeff", "age": 11, "father": "Jack" }
]
const result = fn(children)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

Related

Reverse Order of Properties Per Element in Http Response from JPA/Hibernate Query

if I get a response returning a list of elements like the following:
[
{
"c": {
"c1": 4,
"c2": "5",
},
"b": {
"b1": 2,
"b2": "3",
},
"a": "1"
},
{
"cc": {
"cc1": 4,
"cc2": "5",
},
"bb": {
"bb1": 2,
"bb2": "3",
},
"aa": "1"
}
]
Is there a way I can reverse the order of the properties in each element, while maintaining the element order? I am using JPA/Hibernate. The result should be as follows:
[
{
"a": "1",
"b": {
"b1": 2,
"b2": "3",
},
"c": {
"c1": 4,
"c5": "5",
}
},
{
"aa": "1",
"bb": {
"bb1": 2,
"bb2": "3",
},
"cc": {
"cc1": 4,
"cc2": "5",
}
}
]
Thanks in advance.

d3-sankey links not updating on drag event

Issue-1 : I am unable to update d3-sankey links on drag events. I am trying to replicate d3 vertical and horizontal drag events similar to this : https://bl.ocks.org/d3noob/5028304
When drag event is used it updates the node and the links are not getting updated with it.
I looked into this too https://observablehq.com/#geekplux/dragable-d3-sankey-diagram and I am still having other issues.
I was unable to replicate the code in jsfiddle so I am sharing the JS code here.
const d3 : any = require('d3');
const sankey : any = require('d3-sankey');
const width = 960;
const height = 500;
const svg = d3.select('#chart')
.append('svg')
.attr('viewBox', [0, 0, width, height]);
const formatNumber = d3.format(',.0f');
const format = function (d: any) { return `${formatNumber(d)}TWh`; };
const color = d3.scaleOrdinal(d3.schemeCategory10);
const path = d3.sankeyLinkHorizontal();
const sankeyGraph = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.size([width, height]);
const graph = JSON.parse(JSON.stringify({
nodes: mainData.data.nodes.filter((val:any) => {
return val.name !== '';
})
.map((d : any, i : any) => {
return Object.assign({}, d, { nodeId : i });
}),
links: mainData.data.links.filter((val:any) => {
return (val.source !== '') || (val.target !== '') || (val.value !== '');
})
.map((d : any, i : any) => {
return Object.assign({}, d, { linkId : i });
}),
}));
sankeyGraph(graph);
let link = svg.append('g')
.attr('class', 'links')
.attr('fill', 'none')
.attr('stroke', '#000')
.attr('stroke-opacity', 0.2)
.selectAll('path');
let node = svg.append('g')
.attr('class', 'nodes')
.attr('font-size', 10)
.selectAll('g');
link = link
.data(graph.links)
.enter()
.append('path')
.attr('d', path) // d3.sankeyLinkHorizontal()
.attr('stroke-width', (d: any) => { return Math.max(1, d.width); });
// .on('mouseover', handleMouseOver)
// .on('mouseout', handleMouseOut);
link.append('title')
.text((d: any) => {
return `${d.source.name} → ${d.target.name} -> ${format(d.value)}`;
});
node = node
.data(graph.nodes)
.enter()
.append('g');
node.append('rect')
.attr('x', (d: any) => { return d.x0; })
.attr('y', (d: any) => { return d.y0; })
.attr('height', (d: any) => { return d.y1 - d.y0; })
.attr('width', (d: any) => { return d.x1 - d.x0; })
.attr('fill', (d: any) => { return color(d.name.replace(/ .*/, '')); })
.attr('stroke', '#000')
.call(d3.drag()
.subject((d:any) => d)
// .on('start', () => d3.event.currenTarget.appendChild(d3.event.currenTarget))
.on('drag', dragmove));
function dragmove(d:any, i: number, n: any) { // tslint:disable-line
console.log(d3.event, d3);
// console.log('drag', d3.event.sourceEvent.target, d3.event, d3.sankey);
// const m = d3.select(n[i])
// .node()
// .getCTM();
const x = d3.event.x - d3.event.dx;
const y = d3.event.y - d3.event.dy;
// console.log(m, x, y);
d3.select(n[i])
.attr('x', x)
.attr('y', y);
// *********the issue is here********
d3.sankey(graph)
.update(graph);
// d3.sankey()
// .relayout(graph);
link.attr('d', path); // d3.sankeyLinkHorizontal()
}
node.append('text')
.attr('x', (d: any) => { return d.x0 - 6; })
.attr('y', (d: any) => { return (d.y1 + d.y0) / 2; })
.attr('dy', '0.35em')
.attr('text-anchor', 'end')
.text((d: any) => { return d.name; })
.filter((d: any) => { return d.x0 < width / 2; })
.attr('x', (d: any) => { return d.x1 + 6; })
.attr('text-anchor', 'start');
node.append('title')
.text((d: any) => {
return `${d.name} => ${format(d.value)}`;
});
Issue 2: sometimes this event cannot be used in Vue-D3. So I am having trouble with drag start event code. Please suggest an alternative.
this.parentNode.appendChild(this);
Issue 3: Has anybody replicated the following for sankey with d3-V5. I need the flow/link before and after for each node on hover.
http://bl.ocks.org/tomshanley/11277583
Framework used : Vuejs + typescript
D3 version : 5.9.2
D3 sankey package : https://github.com/d3/d3-sankey
mainData JSON :
"data": {
"nodes": [
{
"name": "Agricultural waste"
},
{
"name": "Bio-conversion"
},
{
"name": "Liquid"
},
{
"name": "Losses"
},
{
"name": "Solid"
},
{
"name": "Gas"
},
{
"name": "Biofuel imports"
},
{
"name": "Biomass imports"
},
{
"name": "Coal imports"
},
{
"name": "Coal"
},
{
"name": "Coal reserves"
},
{
"name": "District heating"
},
{
"name": "Industry"
},
{
"name": "Heating and cooling - commercial"
},
{
"name": "Heating and cooling - homes"
},
{
"name": "Electricity grid"
},
{
"name": "Over generation / exports"
},
{
"name": "H2 conversion"
},
{
"name": "Road transport"
},
{
"name": "Agriculture"
},
{
"name": "Rail transport"
},
{
"name": "Lighting & appliances - commercial"
},
{
"name": "Lighting & appliances - homes"
},
{
"name": "Gas imports"
},
{
"name": "Ngas"
},
{
"name": "Gas reserves"
},
{
"name": "Thermal generation"
},
{
"name": "Geothermal"
},
{
"name": "H2"
},
{
"name": "Hydro"
},
{
"name": "International shipping"
},
{
"name": "Domestic aviation"
},
{
"name": "International aviation"
},
{
"name": "National navigation"
},
{
"name": "Marine algae"
},
{
"name": "Nuclear"
},
{
"name": "Oil imports"
},
{
"name": "Oil"
},
{
"name": "Oil reserves"
},
{
"name": "Other waste"
},
{
"name": "Pumped heat"
},
{
"name": "Solar PV"
},
{
"name": "Solar Thermal"
},
{
"name": "Solar"
},
{
"name": "Tidal"
},
{
"name": "UK land based bioenergy"
},
{
"name": "Wave"
},
{
"name": "Wind"
}
],
"links": [
{
"source": 0,
"target": 1,
"value": 124.729
},
{
"source": 1,
"target": 2,
"value": 0.597
},
{
"source": 1,
"target": 3,
"value": 26.862
},
{
"source": 1,
"target": 4,
"value": 280.322
},
{
"source": 1,
"target": 5,
"value": 81.144
},
{
"source": 6,
"target": 2,
"value": 35
},
{
"source": 7,
"target": 4,
"value": 35
},
{
"source": 8,
"target": 9,
"value": 11.606
},
{
"source": 10,
"target": 9,
"value": 63.965
},
{
"source": 9,
"target": 4,
"value": 75.571
},
{
"source": 11,
"target": 12,
"value": 10.639
},
{
"source": 11,
"target": 13,
"value": 22.505
},
{
"source": 11,
"target": 14,
"value": 46.184
},
{
"source": 15,
"target": 16,
"value": 104.453
},
{
"source": 15,
"target": 14,
"value": 113.726
},
{
"source": 15,
"target": 17,
"value": 27.14
},
{
"source": 15,
"target": 12,
"value": 342.165
},
{
"source": 15,
"target": 18,
"value": 37.797
},
{
"source": 15,
"target": 19,
"value": 4.412
},
{
"source": 15,
"target": 13,
"value": 40.858
},
{
"source": 15,
"target": 3,
"value": 56.691
},
{
"source": 15,
"target": 20,
"value": 7.863
},
{
"source": 15,
"target": 21,
"value": 90.008
},
{
"source": 15,
"target": 22,
"value": 93.494
},
{
"source": 23,
"target": 24,
"value": 40.719
},
{
"source": 25,
"target": 24,
"value": 82.233
},
{
"source": 5,
"target": 13,
"value": 0.129
},
{
"source": 5,
"target": 3,
"value": 1.401
},
{
"source": 5,
"target": 26,
"value": 151.891
},
{
"source": 5,
"target": 19,
"value": 2.096
},
{
"source": 5,
"target": 12,
"value": 48.58
},
{
"source": 27,
"target": 15,
"value": 7.013
},
{
"source": 17,
"target": 28,
"value": 20.897
},
{
"source": 17,
"target": 3,
"value": 6.242
},
{
"source": 28,
"target": 18,
"value": 20.897
},
{
"source": 29,
"target": 15,
"value": 6.995
},
{
"source": 2,
"target": 12,
"value": 121.066
},
{
"source": 2,
"target": 30,
"value": 128.69
},
{
"source": 2,
"target": 18,
"value": 135.835
},
{
"source": 2,
"target": 31,
"value": 14.458
},
{
"source": 2,
"target": 32,
"value": 206.267
},
{
"source": 2,
"target": 19,
"value": 3.64
},
{
"source": 2,
"target": 33,
"value": 33.218
},
{
"source": 2,
"target": 20,
"value": 4.413
},
{
"source": 34,
"target": 1,
"value": 4.375
},
{
"source": 24,
"target": 5,
"value": 122.952
},
{
"source": 35,
"target": 26,
"value": 839.978
},
{
"source": 36,
"target": 37,
"value": 504.287
},
{
"source": 38,
"target": 37,
"value": 107.703
},
{
"source": 37,
"target": 2,
"value": 611.99
},
{
"source": 39,
"target": 4,
"value": 56.587
},
{
"source": 39,
"target": 1,
"value": 77.81
},
{
"source": 40,
"target": 14,
"value": 193.026
},
{
"source": 40,
"target": 13,
"value": 70.672
},
{
"source": 41,
"target": 15,
"value": 59.901
},
{
"source": 42,
"target": 14,
"value": 19.263
},
{
"source": 43,
"target": 42,
"value": 19.263
},
{
"source": 43,
"target": 41,
"value": 59.901
},
{
"source": 4,
"target": 19,
"value": 0.882
},
{
"source": 4,
"target": 26,
"value": 400.12
},
{
"source": 4,
"target": 12,
"value": 46.477
},
{
"source": 26,
"target": 15,
"value": 525.531
},
{
"source": 26,
"target": 3,
"value": 787.129
},
{
"source": 26,
"target": 11,
"value": 79.329
},
{
"source": 44,
"target": 15,
"value": 9.452
},
{
"source": 45,
"target": 1,
"value": 182.01
},
{
"source": 46,
"target": 15,
"value": 19.013
},
{
"source": 47,
"target": 15,
"value": 289.366
}
]
}
Thank you for your solutions in advance.
function sg(mainData) {
const width = 960;
const height = 500;
const svg = d3.select('#chart')
.append('svg')
.attr('viewBox', [0, 0, width, height]);
const formatNumber = d3.format(',.0f');
const format = function (d: any) { return `${formatNumber(d)}TWh`; };
const color = d3.scaleOrdinal(d3.schemeCategory10);
const path = d3.sankeyLinkHorizontal();
const sankeyGraph = d3.sankey()
.nodeWidth(15)
.nodePadding(10)
.size([width, height]);
const graph = JSON.parse(JSON.stringify({
nodes: mainData.data.nodes.filter((val:any) => {
return val.name !== '';
})
.map((d : any, i : any) => {
return Object.assign({}, d, { nodeId : i });
}),
links: mainData.data.links.filter((val:any) => {
return (val.source !== '') || (val.target !== '') || (val.value !== '');
})
.map((d : any, i : any) => {
return Object.assign({}, d, { linkId : i });
}),
}));
sankeyGraph(graph);
let link = svg.append('g')
.attr('class', 'links')
.attr('fill', 'none')
.attr('stroke', '#000')
.attr('stroke-opacity', 0.2)
.selectAll('path');
let node = svg.append('g')
.attr('class', 'nodes')
.attr('font-size', 10)
.selectAll('g');
link = link
.data(graph.links)
.enter()
.append('path')
.attr('d', path) // d3.sankeyLinkHorizontal()
.attr('stroke-width', (d: any) => { return Math.max(1, d.width); });
// .on('mouseover', handleMouseOver)
// .on('mouseout', handleMouseOut);
link.append('title')
.text((d: any) => {
return `${d.source.name} → ${d.target.name} -> ${format(d.value)}`;
});
node = node
.data(graph.nodes)
.enter()
.append('g');
node.append('rect')
.attr('x', (d: any) => { return d.x0; })
.attr('y', (d: any) => { return d.y0; })
.attr('height', (d: any) => { return d.y1 - d.y0; })
.attr('width', (d: any) => { return d.x1 - d.x0; })
.attr('fill', (d: any) => { return color(d.name.replace(/ .*/, '')); })
.attr('stroke', '#000')
.call(d3.drag()
.subject((d:any) => d)
// .on('start', () => d3.event.currenTarget.appendChild(d3.event.currenTarget))
.on('drag', dragmove));
function dragmove(d:any, i: number, n: any) { // tslint:disable-line
console.log(d3.event, d3);
// console.log('drag', d3.event.sourceEvent.target, d3.event, d3.sankey);
// const m = d3.select(n[i])
// .node()
// .getCTM();
const x = d3.event.x - d3.event.dx;
const y = d3.event.y - d3.event.dy;
// console.log(m, x, y);
d3.select(n[i])
.attr('x', x)
.attr('y', y);
// *********the issue is here********
d3.sankey(graph)
.update(graph);
// d3.sankey()
// .relayout(graph);
link.attr('d', path); // d3.sankeyLinkHorizontal()
}
node.append('text')
.attr('x', (d: any) => { return d.x0 - 6; })
.attr('y', (d: any) => { return (d.y1 + d.y0) / 2; })
.attr('dy', '0.35em')
.attr('text-anchor', 'end')
.text((d: any) => { return d.name; })
.filter((d: any) => { return d.x0 < width / 2; })
.attr('x', (d: any) => { return d.x1 + 6; })
.attr('text-anchor', 'start');
node.append('title')
.text((d: any) => {
return `${d.name} => ${format(d.value)}`;
});
}
const data = {
"data": {
"nodes": [{
"name": "Agricultural waste"
},
{
"name": "Bio-conversion"
},
{
"name": "Liquid"
},
{
"name": "Losses"
},
{
"name": "Solid"
},
{
"name": "Gas"
},
{
"name": "Biofuel imports"
},
{
"name": "Biomass imports"
},
{
"name": "Coal imports"
},
{
"name": "Coal"
},
{
"name": "Coal reserves"
},
{
"name": "District heating"
},
{
"name": "Industry"
},
{
"name": "Heating and cooling - commercial"
},
{
"name": "Heating and cooling - homes"
},
{
"name": "Electricity grid"
},
{
"name": "Over generation / exports"
},
{
"name": "H2 conversion"
},
{
"name": "Road transport"
},
{
"name": "Agriculture"
},
{
"name": "Rail transport"
},
{
"name": "Lighting & appliances - commercial"
},
{
"name": "Lighting & appliances - homes"
},
{
"name": "Gas imports"
},
{
"name": "Ngas"
},
{
"name": "Gas reserves"
},
{
"name": "Thermal generation"
},
{
"name": "Geothermal"
},
{
"name": "H2"
},
{
"name": "Hydro"
},
{
"name": "International shipping"
},
{
"name": "Domestic aviation"
},
{
"name": "International aviation"
},
{
"name": "National navigation"
},
{
"name": "Marine algae"
},
{
"name": "Nuclear"
},
{
"name": "Oil imports"
},
{
"name": "Oil"
},
{
"name": "Oil reserves"
},
{
"name": "Other waste"
},
{
"name": "Pumped heat"
},
{
"name": "Solar PV"
},
{
"name": "Solar Thermal"
},
{
"name": "Solar"
},
{
"name": "Tidal"
},
{
"name": "UK land based bioenergy"
},
{
"name": "Wave"
},
{
"name": "Wind"
}
],
"links": [{
"source": 0,
"target": 1,
"value": 124.729
},
{
"source": 1,
"target": 2,
"value": 0.597
},
{
"source": 1,
"target": 3,
"value": 26.862
},
{
"source": 1,
"target": 4,
"value": 280.322
},
{
"source": 1,
"target": 5,
"value": 81.144
},
{
"source": 6,
"target": 2,
"value": 35
},
{
"source": 7,
"target": 4,
"value": 35
},
{
"source": 8,
"target": 9,
"value": 11.606
},
{
"source": 10,
"target": 9,
"value": 63.965
},
{
"source": 9,
"target": 4,
"value": 75.571
},
{
"source": 11,
"target": 12,
"value": 10.639
},
{
"source": 11,
"target": 13,
"value": 22.505
},
{
"source": 11,
"target": 14,
"value": 46.184
},
{
"source": 15,
"target": 16,
"value": 104.453
},
{
"source": 15,
"target": 14,
"value": 113.726
},
{
"source": 15,
"target": 17,
"value": 27.14
},
{
"source": 15,
"target": 12,
"value": 342.165
},
{
"source": 15,
"target": 18,
"value": 37.797
},
{
"source": 15,
"target": 19,
"value": 4.412
},
{
"source": 15,
"target": 13,
"value": 40.858
},
{
"source": 15,
"target": 3,
"value": 56.691
},
{
"source": 15,
"target": 20,
"value": 7.863
},
{
"source": 15,
"target": 21,
"value": 90.008
},
{
"source": 15,
"target": 22,
"value": 93.494
},
{
"source": 23,
"target": 24,
"value": 40.719
},
{
"source": 25,
"target": 24,
"value": 82.233
},
{
"source": 5,
"target": 13,
"value": 0.129
},
{
"source": 5,
"target": 3,
"value": 1.401
},
{
"source": 5,
"target": 26,
"value": 151.891
},
{
"source": 5,
"target": 19,
"value": 2.096
},
{
"source": 5,
"target": 12,
"value": 48.58
},
{
"source": 27,
"target": 15,
"value": 7.013
},
{
"source": 17,
"target": 28,
"value": 20.897
},
{
"source": 17,
"target": 3,
"value": 6.242
},
{
"source": 28,
"target": 18,
"value": 20.897
},
{
"source": 29,
"target": 15,
"value": 6.995
},
{
"source": 2,
"target": 12,
"value": 121.066
},
{
"source": 2,
"target": 30,
"value": 128.69
},
{
"source": 2,
"target": 18,
"value": 135.835
},
{
"source": 2,
"target": 31,
"value": 14.458
},
{
"source": 2,
"target": 32,
"value": 206.267
},
{
"source": 2,
"target": 19,
"value": 3.64
},
{
"source": 2,
"target": 33,
"value": 33.218
},
{
"source": 2,
"target": 20,
"value": 4.413
},
{
"source": 34,
"target": 1,
"value": 4.375
},
{
"source": 24,
"target": 5,
"value": 122.952
},
{
"source": 35,
"target": 26,
"value": 839.978
},
{
"source": 36,
"target": 37,
"value": 504.287
},
{
"source": 38,
"target": 37,
"value": 107.703
},
{
"source": 37,
"target": 2,
"value": 611.99
},
{
"source": 39,
"target": 4,
"value": 56.587
},
{
"source": 39,
"target": 1,
"value": 77.81
},
{
"source": 40,
"target": 14,
"value": 193.026
},
{
"source": 40,
"target": 13,
"value": 70.672
},
{
"source": 41,
"target": 15,
"value": 59.901
},
{
"source": 42,
"target": 14,
"value": 19.263
},
{
"source": 43,
"target": 42,
"value": 19.263
},
{
"source": 43,
"target": 41,
"value": 59.901
},
{
"source": 4,
"target": 19,
"value": 0.882
},
{
"source": 4,
"target": 26,
"value": 400.12
},
{
"source": 4,
"target": 12,
"value": 46.477
},
{
"source": 26,
"target": 15,
"value": 525.531
},
{
"source": 26,
"target": 3,
"value": 787.129
},
{
"source": 26,
"target": 11,
"value": 79.329
},
{
"source": 44,
"target": 15,
"value": 9.452
},
{
"source": 45,
"target": 1,
"value": 182.01
},
{
"source": 46,
"target": 15,
"value": 19.013
},
{
"source": 47,
"target": 15,
"value": 289.366
}
]
}
}
sg(data)
<script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.7.5/typescript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-sankey/0.7.1/d3-sankey.min.js"></script>
<div id="chart"></div>
this works for me.
var node = svg.append('g')
.selectAll('.node')
.data(sankeydata.nodes)
.enter()
.append('g')
.attr('class', 'node')
.attr('transform', d => `translate(${d.x0},${d.y0})`)
.call(d3.drag()
.subject(d => d)
.on('start', function () { this.parentNode.appendChild(this); })
.on('drag', dragmove))
function dragmove(d) {
var rectY = d3.select(this).select("rect").attr("y");
var rectX = d3.select(this).select("rect").attr("X");
d.y0 = d.y0 + d3.event.dy;
d.x1 = d.x1 + d3.event.dx;
d.x0 = d.x0 + d3.event.dx;
var yTranslate = d.y0 - rectY;
var xTranslate = d.x0 - rectX;
d3.select(this).attr('transform', "translate(" + (xTranslate) + "," + (yTranslate) + ")");
sankey.update(graph);
link.attr('d', sankeyLinkHorizontal());
}

How to nest data from a join table in a one (or many) to many relationship in knex.js?

Let's say I have users, skills and user_skill tables.
How can I query so that if I have 3 users, I get 3 objects (in an array, obviously) and for each user's object there should be a nested array with all the skills?
Something like this:
{
"users": [
{
"name": "dusan",
"id": 1,
"facebook": "dusan's facebook",
"skills": [
{"name": "skill1", "id": 1}
{"name": "skill2", "id": 2}
]
},
{
"name": "jenny",
"id": 2,
"facebook": "jenny's facebook",
"skills": [
{"name": "skill1", "id": 1}
{"name": "skill2", "id": 2}
]
},
{
"name": "michael",
"id": 3,
"facebook": "michael's facebook",
"skills": [
{"name": "skill1", "id": 1}
{"name": "skill2", "id": 2}
]
},
]
}
My code:
await db("users")
.join("user_skill", "users.id", "skills.user_id")
.join("skills", "skills.id", "user_skill.id")
.select(
"users.name as name",
"users.id as id",
"skills.name as skill",
"skills.id as skill_id"
);
The above code returns a completely flat structured JSON, and I want to have skills nested inside the user object.
{
"users": [
{
"name": "dusan",
"id": 1,
"skill": "node.js",
"skill_id": 1
},
{
"name": "dusan",
"id": 1,
"skill": "php",
"skill_id": 2
},
{
"name": "dusan",
"id": 1,
"skill": "mongodb",
"skill_id": 3
},
{
"name": "jaca",
"id": 2,
"skill": "angular",
"skill_id": 4
},
{
"name": "jaca",
"id": 2,
"skill": "reactjs",
"skill_id": 5
},
]
}
I understand this is how SQL is designed, to return flat structure, but is there a way I could accomplish the nesting of related data?
A fellow developer has come up with this solution, so I've decided to share it in hope that someone would find it helpful:
returnedUsers = {
"users": [{
"name": "dusan",
"id": 1,
"skill": "node.js",
"skill_id": 1
},
{
"name": "dusan",
"id": 1,
"skill": "php",
"skill_id": 2
},
{
"name": "dusan",
"id": 1,
"skill": "mongodb",
"skill_id": 3
},
{
"name": "jaca",
"id": 2,
"skill": "angular",
"skill_id": 4
},
{
"name": "jaca",
"id": 2,
"skill": "reactjs",
"skill_id": 5
},
]
};
const groupBy = (array, key) =>
array.reduce((a, c) => ({
...a,
[c[key]]: [...a[c[key]] || [], c]
}), {});
const uniques = (...values) =>
Array.from(new Set([].concat(...values).filter(Boolean)));
const singularize = array =>
array.length == 1 ? array[0] : array;
const singularizedUniques = (...values) =>
singularize(uniques(...values));
const mergeCollect = array =>
array.reduce((mergedObject, curentObject) =>
Object.entries(curentObject).reduce((newObject, [k, v]) => ({
...newObject,
[k]: singularizedUniques(newObject[k], v)
}), mergedObject), {});
const groupByKey = (array, key) =>
Object.fromEntries(Object.entries(groupBy(array, key)).map(([k, v]) => [k, mergeCollect(v)]));
console.log(groupByKey(returnedUsers.users, 'id'));

Mule Dataweave orderby multiple value

I would like to know how to sort a collection in mule using Dataweave orderBy with multiple number of fields and also with ascending or descending order.
Here is the sample code(with example) that I created to demonstrate multiple orderby and sorting. Note:- By default, the order by is ascending order and to achieve the descending order, just reverse the result at the end by [-1..0].
%dw 1.0
%var inputPayload=[
{"name":"john",
"age": "12"
},
{"name":"john3",
"age": "15"
},
{"name":"john3",
"age": "14"
},
{"name":"john1",
"age": "13"
},
{"name":"john2",
"age": "14"
},
{"name":"john5",
"age": "17"
}
]
%output application/json
---
((inputPayload orderBy $.name) orderBy $.age)[-1..0]
Output Payload - [ {
"name": "john5",
"age": "17" }, {
"name": "john3",
"age": "15" }, {
"name": "john3",
"age": "14" }, {
"name": "john2",
"age": "14" }, {
"name": "john1",
"age": "13" }, {
"name": "john",
"age": "12" } ]
You have to use the OrderBy and concatenate operator for this. Giving an example below
payload orderBy ($.name ++ $.id)
I think the accepted answer just re-orders the entire array twice and only works for that particular example. If you use an example where the age a number instead of a string like so
{
"input": [
{
"name": "john",
"age": 12
},
{
"name": "john5",
"age": 7
},
{
"name": "john3",
"age": 15
},
{
"name": "john3",
"age": 14
},
{
"name": "john1",
"age": 13
},
{
"name": "john2",
"age": 14
}
]
}
then the output ends up in the wrong order for a multi-layer orderBy (it's the order you would expect if we just did orderBy age)
[
{
"name": "john3",
"age": 15
},
{
"name": "john3",
"age": 14
},
{
"name": "john2",
"age": 14
},
{
"name": "john1",
"age": 13
},
{
"name": "john",
"age": 12
},
{
"name": "john5",
"age": 7
}
]
whereas something like
flatten(((inputPayload orderBy $.name) groupBy $.name) pluck ($ orderBy $.age))[-1..0] gives
[
{
"name": "john5",
"age": 7
},
{
"name": "john3",
"age": 15
},
{
"name": "john3",
"age": 14
},
{
"name": "john2",
"age": 14
},
{
"name": "john1",
"age": 13
},
{
"name": "john",
"age": 12
}
]
so the overall orderBy is name and then within the same name the orderBy is age

How to get values in an array from nested array of objects based on a given condition?

I'm using lodash and I have the following array of objects:
[{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
}
]
}]
What i'm trying to get the list of ID and name for a given "SUB".
So, with the previous object, if I send the sub fr I want to get:
[{
"id": 1,
"name": "foobar1"
},
{
"id": 2,
"name": "foobar3"
}]
Do you know if I can easily do it with lodash?
I tried to use _.pick but it doesn't working(I'm a bit lost with these mixes between nested objects and arrays) _.map(data, function (o) { _.pick(o, ['id', 'values.name']) });.
I also tried to use _.filter with things like _.filter(data, { values: [{ sub: 'fr' }]}); but it return all the items. What I'm looking for is to return the nested part only.
You can use flatMap() where its callback returns an array of filtered subs using filter() where each filtered item is transformed using map().
var result = _.flatMap(data, item =>
_(item.values)
.filter({ sub: 'fr' })
.map(v => ({id: item.id, name: v.name}))
.value()
);
var data = [{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
}
]
}];
var result = _.flatMap(data, item =>
_(item.values)
.filter({ sub: 'fr' })
.map(v => ({id: item.id, name: v.name}))
.value()
);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
following #ryeballar's answer, a shorter version with map
var result = _.map(data, item => ({id: item.id, name: item.name}));