How to get a desired output using groupBy in dataweave? - mule

I'm looking for an output similar to this one below where i want to groupBy costomer and orderid.
Input:
[
{
"item": 621,
"orderid": "ON22",
"qty": 45.0,
"customer": "610",
"date": "1988-08-13"
},
{
"item": 63,
"orderid": "ON2234",
"qty": 7,
"customer": "813",
"date": "2001-08-13"
}
]
Desired output:
[
{
"customer":"813",
"data":[
{
"item":63,
"qty":7,
"orderid":"ON2234",
"date":"2001-08-13"
}
]
},
{
"customer":"610",
"data":[
{
"item": 621,
"qty": 45.0,
"orderid": "ON22",
"date": "1988-08-13"
}
]
}
]

You can simply map the default output of your groupBy result since your output does not require any additional logic.
%dw 2.0
output application/json
---
payload groupBy $.customer pluck ((customerOrders, customerId) -> {
customer: customerId as String,
data: customerOrders
})

Related

how can I loop through the payload and search within the same payload in another array with similar structure and alter matches

I have entered the payload as shown below, but I have to replace the values ​​of "labelnumber" with the similar number from the main line array with the matches "payload.lines.number = payload.notification.body.lines.number" that are inside the line array inside the notification element, can anyone help me how can we replace it.
input payload
{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "456",
"labelnumber":"DFG",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
}
],
"notification":{
"body":{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "123",
"labelnumber":"",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "456",
"labelnumber":"",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"",
"received": "2022-11-15T19:31:49.042Z"
}
]
}
}
}
expected payload
{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "456",
"labelnumber":"DFG",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
}
],
"notification":{
"body":{
"date": "2022-11-15T19:24:36.871Z",
"lines": [
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:17.955Z"
},
{
"number": "123",
"labelnumber":"ABC",
"received": "2022-11-15T19:30:57.426Z"
},
{
"number": "456",
"labelnumber":"DFG",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
},
{
"number": "789",
"labelnumber":"HIJ",
"received": "2022-11-15T19:31:49.042Z"
}
]
}
}
}
As you can see in this example, I need to loop through the main row array and find the matches within the notification array and assign the corresponding value.
NOTE: maybe in the notification.body has many elements and I don't need to change them and I don't know the name of its elements, in this case it only has "date" but I need to keep them as they are.
With the update operator you can update only the keys that you want. This solution assumes that all the number values are defined in payload.lines.
%dw 2.0
output application/json
---
payload update {
case lines at .notification.body.lines -> lines map ((item, index) ->
item update {
case .labelnumber -> (payload.lines filter ($.number == item.number))[0].labelnumber
}
)
}
Converting reference line Array to Hashmap will help replace values efficiently instead of looping every time. Following code will work
%dw 2.0
output application/json
var lineMap = {(payload.lines map {
($.number) : $.labelnumber
})}
var modifiedLines = (payload.notification.body.lines map ((item, index) -> {
data : item mapObject ((value, key, dataindex) -> {
(key) : if (key ~= 'labelnumber') lineMap[item.number] else value
})
})).data
---
(payload - 'notification') ++
{
"notification":{
"body":{
"lines": modifiedLines
}
}
}
Update : with updated requirement body can have any fields
%dw 2.0
import * from dw::util::Values
output application/json
var lineMap = {(payload.lines map {
($.number) : $.labelnumber
})}
var modifiedLines = payload.notification.body.lines map ((item, index) -> item update 'labelnumber' with lineMap[item.number])
var body = (payload.notification.body - 'lines') ++ {lines : modifiedLines}
---
(payload - 'notification') ++
{
"notification":{
"body": body
}
}

dataweave - How can i get total of the order Mule 4

I have the following scenario and problem, I recive by CSV File and mapping with DW, groupping by column "PON", i need to get the total of the order multiply this column ( Qty * Price ), I don't have the correct result, I will show you:
CSV Data:
PON,Item,Qty,Price
PON1000,2015,2,38.08
PON1000,2016,1,33.37
PON1001,2015,2,38.08
DW:
%dw 2.0
output application/json
---
payload groupBy ($.PON) pluck $ map ( () -> {
"order": $[0].PON default "",
"total": (sum( $.Price filter ($ != "") ) as Number) as String {format: "##,###.00"},
"products": $ map {
"product": $.Item,
"price": ($.Price as Number) as String {format: "##,###.00"},
"quantity": $.Qty
}
})
Obtained Result:
[
{
"order": "PON1000",
"total": "71.45",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
},
{
"product": "2016",
"price": "33.37",
"quantity": "1"
}
]
},
{
"order": "PON1001",
"total": "38.08",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
}
]
}
]
I NEED MULTIPLY BY ORDER THE "price" * "quantity" CORRESPONDENT AND FINALLY SUM THAT VALUE AND PUT IN THE COLUMN total by ORDER
Expected Result:
[
{
"order": "PON1000",
"total": "109.53",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
},
{
"product": "2016",
"price": "33.37",
"quantity": "1"
}
]
},
{
"order": "PON1001",
"total": "76.16",
"products": [
{
"product": "2015",
"price": "38.08",
"quantity": "2"
}
]
}
]
Any help would be appreciated. Thank you.
Best Regards!!!
I just added two things:
For the total I used Arrays::sumBy which let's you do an operation on each item and the it sums all the results.
I infered from your code you expect the price to be empty, so I created safeNumber() to check that and return 0 in case it's empty (default did not work).
This is the code I've got so far:
%dw 2.0
output application/json
import * from dw::core::Arrays
fun safeNumber(str) = if(isEmpty(str)) 0 else str as Number
---
payload groupBy ($.PON) pluck $ map ( () -> {
"order": $[0].PON default "",
"total": ($ sumBy( (i) -> safeNumber(i.Qty) * safeNumber(i.Price))) as String {format: "##,##0.00"},
"products": $ map {
"product": $.Item,
"price": safeNumber($.Price) as String {format: "##,##0.00"},
"quantity": $.Qty
}
})
Below script will help you.
%dw 2.0
output application/json
import divideBy from dw::core::Objects
---
payload groupBy $.PON mapObject ((value, key, index) ->
({
order: (key),
total: sum(value map ($.Qty * $.Price)),
value : value
})
) divideBy 3
You can use the following DataWeave expression:
%dw 2.0
output application/json
---
payload groupBy $.PON pluck $ map (() -> {
"order": $[0].PON,
"total": sum($ map ($.Qty as Number * $.Price as Number)),
"products": $ map {
"product": $.Item,
"price": $.Price as Number,
"quantity": $.Qty as Number
}
})

Dataweave 2 - How can i join 2 arrays by index inside object without lose data parent object

How to join 3 arrays by index (lines, pckSlip and linesDt) and generate an arrays object by linesDt after that you have to generate a new field "totalCost" which is to add the "cost" field of all cost elements in the linesDt array, note the "number" field in the original object is preserved for all new elements spawned from the parent.
Input:
{
"lines":[
{
"requestedQuantity":1,
"pendingQuantity":0
},
{
"requestedQuantity":2,
"pendingQuantity":0
}
],
"number":"98",
"pckSlip":[
{
"trackingNumber":"10534",
"boxesNum":1
},
{
"trackingNumber":"00049",
"boxesNum":1
}
],
"linesDt":[
{
"number":"5678",
"cost":7.7
},
{
"number":"1234",
"cost":7.3
}
]
}
Ouput:
[
{
"number":"5678",
"cost":7.7,
"requestedQuantity":1,
"pendingQuantity":0,
"trackingNumber":"10534",
"boxesNum":1,
"totalCost":15,
"order":"98"
},
{
"number":"1234",
"cost":7.3,
"requestedQuantity":2,
"pendingQuantity":0,
"trackingNumber":"00049",
"boxesNum":1,
"totalCost":15,
"order":"98"
}
]
NOTE: We generate 2 new elements because they are the total of indices found in "linesDt" within an array of elements.
Any help would be appreciated. Thank you.
Mapping each element of lines gives you the index to use in the other arrays. The ++ operator can be used to concatenate objects all the objects together. The calculated fields are added just as another object.
%dw 2.0
output application/json
var totalCost = sum(payload.linesDt.*cost)
---
payload.lines map (
$
++ payload.pckSlip[$$]
++ payload.linesDt[$$]
++ {totalCost: totalCost, order: payload.number}
)
Output:
[
{
"requestedQuantity": 1,
"pendingQuantity": 0,
"trackingNumber": "10534",
"boxesNum": 1,
"number": "5678",
"cost": 7.7,
"totalCost": 15.0,
"order": "98"
},
{
"requestedQuantity": 2,
"pendingQuantity": 0,
"trackingNumber": "00049",
"boxesNum": 1,
"number": "1234",
"cost": 7.3,
"totalCost": 15.0,
"order": "98"
}
]
Assuming that the size of each of the arrays is going to be the same.
Script
%dw 2.0
output application/json
---
1 to sizeOf(payload.lines) map {
(payload.linesDt[($$)] ++ payload.lines[($$)] ++ payload.pckSlip[($$)] ++ ("totalCost": sum(payload.linesDt..cost) as String) ++ ("order": payload.number))
}
Output
[
{
"number": "5678",
"cost": 7.7,
"requestedQuantity": 1,
"pendingQuantity": 0,
"trackingNumber": "10534",
"boxesNum": 1,
"totalCost": "15",
"order": "98"
},
{
"number": "1234",
"cost": 7.3,
"requestedQuantity": 2,
"pendingQuantity": 0,
"trackingNumber": "00049",
"boxesNum": 1,
"totalCost": "15",
"order": "98"
}
]

Need to convert the payload to the desired output

In the below array there can be multiple objects, and each object can have more than below mentioned key values. I need only the uniqueID and name fields to be displayed.
[
{
"uniqueID": "1",
"Name": "Annie",
"Standard": "3",
"School" : "ABC School"
},
{
"uniqueID": "2",
"Name": "Apoo",
"Standard": "4",
"School" : "PQR School"
},
{
"uniqueID": "3",
"Name": "Xavier",
"Standard": "5",
"School" : "MNO School"
}
]
Desired output:
{
"errors": [
{
"uniqueID": "1",
"Name": "Annie"
},
{
"uniqueID": "2",
"Name": "Apoo"
},
{
"uniqueID": "3",
"Name": "Xavier"
}
]
}
Couple of approaches.
Script
%dw 2.0
output application/json
---
errors: payload map {
uniqueID: $.uniqueID,
Name: $.Name
}
%dw 2.0
output application/json
---
errors: payload map {
($ - "Standard" - "School")
}
In addition to Salim Khan's answer, another way is to use filterObject() to let only the desired attributes in the output. The advantage is that it is somewhat more generic if other attributes are added or changed.
%dw 2.0
output application/json
var allowedKeydNames=["uniqueID", "Name"]
---
{
errors: payload map (
$ filterObject ((value, key, index) -> (allowedKeydNames contains (key as String)))
)
}

"Transform JSON to JSON with applying groupBy"

I'm transforming payload from json to json with applying groupBy condition but I am not getting proper data what I want.
I have to group the Employee and list his all the tasks.
Currently I am able to apply groupBy employee but his all task is not showing.
payload is:
[
{
"Id": 1,
"EmployeeName": "AA",
"Task": {
"TaskName": "Deploy"
}
},
{
"Id": 1,
"EmployeeName": "AA",
"Task": {
"TaskName": "Test"
}
},
{
"Id": 3,
"EmployeeName": "BB",
"Task": {
"TaskName": "Deploy"
}
}
]
This is my transformation code:
%dw 1.0
%output application/json
---
(payload groupBy ($.EmployeeName ++ $.Id)) map {
EmployeeName : $[0].EmployeeName,
Email : $[0].Email,
Task: $[0].Task
}
This is what I am getting:
[
{
"EmployeeName": "AA",
"Task": {
"TaskName": "Deploy"
}
},
{
"EmployeeName": "BB",
"Task": {
"TaskName": "Deploy"
}
}
]
Expected result:
[
{
"EmployeeName": "AA",
"Task1": {
"TaskName": "Deploy"
},
"Task2": {
"TaskName": "Test"
}
},
{
"EmployeeName": "BB",
"Task1": {
"TaskName": "Deploy"
}
}
]
How can I modify my dataweave to get the expected result.
Following code should work fine.
%dw 1.0
%output application/json
---
payload groupBy ($.Id ++ $.EmployeeName) map {
EmployeeName : $[0].EmployeeName,
({Task : {($.Task map {
('Task' ++ $$ + 1) : $
})}})
}
Hope this helps.