How to filter the sku empty and remove all the coincidense that the same order number - mule

There is an array of parent elements that you need filter and remove if the sky are empty and get the number and remove all the coincidences of the principal array.
Input:
[{
"number": "7358",
"sku": "301-01"
}, {
"number": "7358",
"sku": "301-02"
}, {
"number": "7359",
"sku": ""
}, {
"number": "7359",
"sku": "301-04"
}, {
"number": "7356",
"sku": ""
}, {
"number": "7356",
"sku": "301-05"
}, {
"number": "7356",
"sku": "301-07"
}]
Output:
[{
"number": "7358",
"sku": "301-01"
}, {
"number": "7358",
"sku": "301-02"
}]
In Output we only find the elements that complied with having their sku with content.

Try with this script:
The idea is to collect all number(s) where the sku is "" and create an array out of these. After that you can iterate through the payload and filter out objects where the number in the object is present in the array created in the previous step.
%dw 2.0
output application/json
var atleastOneEmptySku = (payload filter ($.sku == ""))..number
---
payload filter (!(atleastOneEmptySku contains $.number))

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
}
})

Karate - How count number of instances of element in JSON response with embedded elements

I want to work out the total number of occurences of 'id' in the following JSON String.
Does Karate have a quick way of doing this?
If it was at the top level I could do response.result.length but they are are in the embedded elements of 'test'. I could do this in javascript but just wondering if Karate has a quicker method.
{
"result": [
{
"test": [
{
"id": "x",
"price": "£5.00"
},
{
"id": "y",
"price": "£10.00"
},
{
"id": "z",
"price": "£10.00"
},
{
"id": "a",
"price": "£10.00"
}
]
},
{
"test": [
{
"id": "b",
"price": "£5.00"
},
{
"id": "c",
"price": "£10.00"
}
]
}
]
}
Here you go:
* def ids = $..id
* assert ids.length == 6
Do take some time to read about JsonPath in the docs.

Nested array data transformation with Mule 3

I am trying to transform data in Mule 3 (DataWeave 1.0) but I am not getting the desire result.
This is the input payload:
[
"https://scrum-caller.com/repo/v1/inside#Changes",
[
{
"id": "8db55441-6255-4d24-8d39-658536985214",
"number": "0w-30",
"Desc": "maintain"
}
],
"https://scrum-caller.com/repo/v1/inside#Changes",
[
{
"id": "11111111-6666-2222-3g3g-854712547412",
"number": "5w-40",
"Desc": "on prod"
}
],
"https://scrum-caller.com/repo/v1/inside#Changes",
[
{
"id": "1ab32c5b-ffs3-3243-74fv-3376218042bb",
"number": "5w-30",
"Desc": "on test"
}
]
]
And my desire output need to be like the one below
{
"#odata.context": "https://scrum-caller.com/repo/v1/inside#Changes",
"value": [
{
"id": "8db55441-6255-4d24-8d39-658536985214",
"number": "0w-30",
"Desc": "maintain"
},
{
"id": "11111111-6666-2222-3g3g-854712547412",
"number": "5w-40",
"Desc": "on prod"
},
{
"id": "1ab32c5b-ffs3-3243-74fv-3376218042bb",
"number": "5w-30",
"Desc": "on test"
}
]
}
Thanks for helping guys.
Assuming all the URLs are the same, since the question doesn't provide details only an example, I just take the first element as the value of the input for "#odata.context", the the value is just filtering out the non-array elements and use the reduce operator to get a single array of the other elements.
%dw 1.0
%output application/json
---
{
"#odata.context" : payload[0],
value : payload filter ($ is :array) reduce ($ ++ $$)
}

Filtering out objects from multiple arrays in a JSONB column

I have a JSON structure with two arrays saved in a JSONB column. A bit simplified it looks like this
{
"prop1": "abc",
"prop2": "xyz",
"items": [
{
"itemId": "123",
"price": "10.00"
},
{
"itemId": "124",
"price": "9.00"
},
{
"itemId": "125",
"price": "8.00"
}
],
"groups": [
{
"groupId": "A",
"discount": "20",
"discountId": "1"
},
{
"groupId": "B",
"discount": "30",
"discountId": "2"
},
{
"groupId": "B",
"discount": "20",
"discountId": "3"
},
{
"groupId": "C",
"discount": "40",
"discountId": "4"
}
]
}
Schema:
CREATE TABLE campaign
(
id TEXT PRIMARY KEY,
data JSONB
);
Since each row (data column) can be fairly large, I'm trying to filter out matching item objects and group objects from the items and groups arrays.
My current query is this
SELECT * FROM campaign
WHERE
(data -> 'items' #> '[{"productId": "123"}]') OR
(data -> 'groups' #> '[{"groupId": "B"}]')
which returns rows containing either the matching group or the matching item. However, depending on the row, the data column can be a fairly large JSON object (there may be hundreds of objects in items and tens in groups and I've omitted several keys/properties for brevity in this example) which is affecting query performance (I've added GIN indexes on the items and groups arrays, so missing indices is not why it's slow).
How can I filter out the items and groups arrays to only contain matching elements?
Given this matching row
{
"prop1": "abc",
"prop2": "xyz",
"items": [
{
"itemId": "123",
"price": "10.00"
},
{
"itemId": "124",
"price": "9.00"
},
{
"itemId": "125",
"price": "8.00"
}
],
"groups": [
{
"groupId": "A",
"discount": "20",
"discountId": "1"
},
{
"groupId": "B",
"discount": "30",
"discountId": "2"
},
{
"groupId": "B",
"discount": "20",
"discountId": "3"
},
{
"groupId": "C",
"discount": "40",
"discountId": "4"
}
]
}
I'd like the result to be something like this (the matching item/group could be in different columns from the rest of the data column - doesn't have to be returned in a single JSON object with two arrays like this, but I would prefer it if doesn't affect performance or lead to a really hairy query):
{
"prop1": "abc",
"prop2": "xyz",
"items": [
{
"itemId": "123",
"price": "10.00"
}
],
"groups": [
{
"groupId": "B"
"discount": "20",
"discountId": "3"
}
]
}
What I've managed to do so far is unwrap and match an object in the items array using this query, which removes the 'items' array from the data column and filters out the matching item object to a separate column, but I'm struggling to join this with matches in the groups array.
SELECT data - 'items', o.obj
FROM campaign c
CROSS JOIN LATERAL jsonb_array_elements(c.data #> '{items}') o(obj)
WHERE o.obj ->> 'productId' = '124'
How can I filter both arrays in one query?
Bonus question: For the groups array I also want to return the object with the lowest discount value if possible. Or else the result would need to be an array of matching group objects instead of a single matching group.
Related questions: How to filter jsonb array elements and How to join jsonb array elements in Postgres?
If your postgres version is 12 or more, you can use the jsonpath language and functions. The query below returns the expected result with the subset of items and groups which match the given criteria. Then you can adapt this query within a sql function so that the search criteria is an input parameter.
SELECT jsonb_set(jsonb_set( data
, '{items}'
, jsonb_path_query_array(data, '$.items[*] ? (#.itemId == "123" && #.price == "10.00")'))
, '{groups}'
, jsonb_path_query_array(data, '$.groups[*] ? (#.groupId == "B" && #.discount == "20" && #.discountId == "3")'))
FROM (SELECT
'{
"prop1": "abc",
"prop2": "xyz",
"items": [
{
"itemId": "123",
"price": "10.00"
},
{
"itemId": "124",
"price": "9.00"
},
{
"itemId": "125",
"price": "8.00"
}
],
"groups": [
{
"groupId": "A",
"discount": "20",
"discountId": "1"
},
{
"groupId": "B",
"discount": "30",
"discountId": "2"
},
{
"groupId": "B",
"discount": "20",
"discountId": "3"
},
{
"groupId": "C",
"discount": "40",
"discountId": "4"
}
]
}' :: jsonb) AS d(data)
WHERE jsonb_path_exists(data, '$.items[*] ? (#.itemId == "123" && #.price == "10.00")')
AND jsonb_path_exists(data, '$.groups[*] ? (#.groupId == "B" && #.discount == "20" && #.discountId == "3")')