Mule Dataweave orderby multiple value - mule

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

Related

How to apply filter for nested arrays in mulesoft dataWeave

I tried to filter below json payload characters[] array which is having result as 'valid' and data[] array name as 'WBB' and priority as '1'
I tried below code but not working can some one help me ?.
flatten(payload.offers.category.characters) filter ((item, index) -> item.result=='valid' and flatten(item.data) filter ((item, index) -> item.name=='WBB' and item.priority==1))
Json payload
{
"offers": [
{
"id": 100,
"name": "Test1",
"category": {
"characters": [
{
"result": "valid",
"data": [
{
"name": "WBB",
"priority": 1
},
{
"name": "ILL",
"priority": 2
}
]
}
]
}
},
{
"id": 200,
"name": "Test2",
"category": {
"characters": [
{
"data": [
{
"name": "ISS",
"priority": 1
},
{
"name": "ILL",
"priority": 2
}
]
}
]
}
},
{
"id": 300,
"name": "Test3",
"category": {
"characters": [
{
"data": [
{
"name": "WSS",
"priority": 1
},
{
"name": "ILL",
"priority": 2
}
]
}
]
}
}
]
}
Expected payload
[
{
"name": "WBB",
"priority": 1
}
]
flatten((flatten(payload.offers..characters) filter $.result == "valid").data) filter ($.name=="WBB" and $.priority == 1)
flatten(payload..data) filter ((item, index) -> item.name == 'WBB' )

Get the root key with jsonb_path_query()

In Postgres 13, for the below query, the jsonb values are getting filtered correctly based on "priority":
SELECT jsonb_path_query(
'{
"100": {
"name": "test",
"priority": 5
},
"101": {
"name": "test2",
"priority": 10
},
"102": {
"name": "test3",
"priority": 15
}
}'
, '$.* ? (#.priority > 10)')
Output:
{
"name": "test3",
"priority": 15
}
But I want to get the root key also. In this case I want to get the root for "test3" which is "102". To achieve this, I tried the below query:
SELECT jsonb_path_query(
'{
"100": {
"name": "test",
"priority": 5
},
"101": {
"name": "test2",
"priority": 10
},
"102": {
"name": "test3",
"priority": 15
}
}'
, '$ ? (#.*.priority > 10)')
But the output data is not getting filtered based on "priority".
Here is the output:
{
"100": {
"name": "test",
"priority": 5
},
"101": {
"name": "test2",
"priority": 10
},
"102": {
"name": "test3",
"priority": 15
}
}
The desired output would be:
{
"102": {
"name": "test3",
"priority": 15
}
}
How can I filter the data using an SQL/JSON path expression and the get the root key as well?
The task would be simple with a JSON array instead of a JSON object (which would seem like the more appropriate structure for your sample data):
SELECT jsonb_path_query(
'[
{
"100": {
"name": "test",
"priority": 5
}
},
{
"101": {
"name": "test2",
"priority": 10
}
},
{
"102": {
"name": "test3",
"priority": 15
}
}
]'
, '$[*] ? (#.*.priority > 10)');
While working with a JSON object, one way would be with the .keyvalue() method:
SELECT jsonb_path_query(
'{
"100": {
"name": "test",
"priority": 5
},
"101": {
"name": "test2",
"priority": 10
},
"102": {
"name": "test3",
"priority": 15
}
}'
, '$.keyvalue() ? (#.value.priority > 10)');
Returns:
{"id": 0, "key": "102", "value": {"name": "test3", "priority": 15}}
The manual:
object . keyvalue() → array
The object's key-value pairs, represented as an array of objects
containing three fields: "key", "value", and "id"; "id" is a
unique identifier of the object the key-value pair belongs to
To get your desired JSON value exactly:
SELECT jsonb_build_object(j->>'key', j->'value')
FROM (
SELECT jsonb_path_query(
'{
"100": {
"name": "test",
"priority": 5
},
"101": {
"name": "test2",
"priority": 10
},
"102": {
"name": "test3",
"priority": 15
}
}'
, '$.keyvalue() ? (#.value.priority > 10)')
) sub(j);
Returns:
{"102": {"name": "test3", "priority": 15}}
db<>fiddle here

Grouping Response Data

I am trying to get data from my database but when I show and make it become api response, I have some problem for grouping it based on productid.
I have response data that created based on golang like this:
[
{
"product_id": "1",
"product_name": "Cardigan",
"pitems": [
{
"id": "625ad1bc-66c5-440e-a527-d029d401ec2b",
"name": "Box",
"qty": 1
},
{
"id": "625ad1bc-66c6-440e-a527-d029d401ec2b",
"name": "test items1",
"qty": 1
},
{
"id": "625ad1bc-66c7-440e-a527-d029d401ec2b",
"name": "test items2",
"qty": 1
},
{
"id": "625ad1bc-66c8-440e-a527-d029d401ec2b",
"name": "test items3",
"qty": 1
}
]
},
{
"product_id": "2",
"product_name": "Polo",
"product_sku": "P01",
"items": [
{
"id": "625ad1bc-66c5-440e-a527-d029d401ec2b",
"name": "Box",
"qty": 1
},
{
"id": "625ad1bc-66c6-440e-a527-d029d401ec2b",
"name": "test items1",
"qty": 1
},
{
"id": "625ad1bc-66c7-440e-a527-d029d401ec2b",
"name": "test items2",
"qty": 1
},
{
"id": "625ad1bc-66c8-440e-a527-d029d401ec2b",
"name": "test items3",
"qty": 1
}
]
}
]
But This response is not my expected result, my expected result is like:
[
{
"product_id": "1",
"product_name": "Cardigan",
"pitems": [
{
"id": "625ad1bc-66c5-440e-a527-d029d401ec2b",
"name": "Box",
"qty": 1
},
{
"id": "625ad1bc-66c6-440e-a527-d029d401ec2b",
"name": "test items1",
"qty": 1
},
{
"id": "625ad1bc-66c7-440e-a527-d029d401ec2b",
"name": "test items2",
"qty": 1
}
]
},
{
"product_id": "2",
"product_name": "Polo",
"product_sku": "P01",
"items": [
{
"id": "625ad1bc-66c8-440e-a527-d029d401ec2b",
"name": "test items3",
"qty": 1
}
]
}
]
Can Anyone help me to solve my problem?
What does it mean to show detailed data?
the easy way is:
create 2 func like this:
func detail(id int)(result model.Struct)
{ return result }
func product()(result model.Struct_Result) {
for data.Next() {
// call func detail
data.Scan(&id, &product)
detailResult := detail(id)
// then put together with struct and mix append ()
outputLoop := model.Result{
"product_id": id,
"pitems": [
{
"id": detailResult.id,
"name": detailResult.name,
"qty": detailResult.qty
},
]
}
result = append(result,outputLoop)
}
return result
}

Compare 2 JSON arrays to get matching and un-matching outputs

I need to compare 2 JSON arrays using Mule 4 dataweave 2.0 to get matching and un-matching outputs.
The sample input JSON payload is given below:
[
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
This has to be compared to the below on ID/IDENTITY field.
[
{
"IDENTITY": "D40000",
"NM": "Delta"
},
{
"IDENTITY": "C30000",
"NM": "Charlie"
}
]
My expected output is 2 variable arrays containing matching and un-matching objects:
varMatch:
[
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
}
]
varUnmatch:
[
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
If that ID map is coming from somewhere else and you can't change its structure, I'd probably remap it and then use it like so:
%dw 2.0
output application/json
var identMap = [
{
"IDENTITY": "D40000",
"NM": "Delta"
},
{
"IDENTITY": "C30000",
"NM": "Charlie"
}
]
var remapped = identMap reduce ((item,accum={}) -> accum ++ (item.IDENTITY): 1)
---
payload groupBy (if (remapped[$.ID]?) "varMatched" else "varUnmatched")
which produces
{
"varUnmatched": [
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
],
"varMatched": [
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
}
]
}
Hope this helps
%dw 2.0
var input1=[{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
var input2=[
{
"IDENTITY": "D40000",
"NM": "Delta"
},
{
"IDENTITY": "C30000",
"NM": "Charlie"
}
]
var varMatch = input1 map $ filter (input2.IDENTITY contains $.ID)
var varUnmatch = input1 -- varMatch
output application/json
---
{
varMatch: varMatch,
varUnmatch: varUnmatch
}
Sample Output
{
"varMatch": [
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
}
],
"varUnmatch": [
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
}
Here's another solution, albeit the previous two are solving your problem:
%dw 2.0
output application/dw
var data = [
{
"CODE": "A11",
"NAME": "Alpha",
"ID": "C10000"
},
{
"CODE": "B12",
"NAME": "Bravo",
"ID": "B20000"
},
{
"CODE": "C11",
"NAME": "Charlie",
"ID": "C30000"
},
{
"CODE": "D12",
"NAME": "Delta",
"ID": "D40000"
},
{
"CODE": "E12",
"NAME": "Echo",
"ID": "E50000"
}
]
var searchData = [
{
"IDENTITY": "D40000",
"NM": "Delta"
},
{
"IDENTITY": "C30000",
"NM": "Charlie"
}
]
---
data dw::core::Arrays::partition (e) -> searchData.*IDENTITY contains e.ID
Pick the one that perfoms the best and use it.

RamdaJS groupBy and tranform object

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>