improve leftJoin nested mapObject when equivalence do and do not match

Viewed 100

I am using the following dataweave function, and it does works.

%dw 2.0
import * from dw::core::Arrays
output application/json

var mysqlInvoices = [
    {
        "id": 1,
        "owner": "Joseph"
    },
    {
        "id": 2,
        "owner": "Maria"
    }
]

var sapInvoices = [
    {
        "number": 3,
        "issuedBy": "XYZ"
    },
    {
        "number": 4,
        "issuedBy": "ABC"
    }
]
---
leftJoin(mysqlInvoices, sapInvoices, (m) -> m.id, (s) -> s.number) map (item, index) -> 
  (item.l mapObject (sItem, sKey) -> 
        (if ((sKey) as String == "id") "identifier" 
        else if ((sKey) as String == "owner") "ownerName" 
        else (sKey)): sItem)
  ++ 
  (if (item.r != null) 
    item.r mapObject (sItem, sKey) -> 
        (sKey): sItem
  else 
    sapInvoices[0] mapObject 
        (sItem, sKey) -> (sKey): "") 

However, I am thinking if I can improve this function at two points:

  1. change the key conditions:

I dont think that is the best practice to check every key match an if condition to change it:

(if ((sKey) as String == "id") "identifier" 
else if ((sKey) as String == "owner") "ownerName" 
else (sKey)): sItem
  1. Use the original object to map it as an empty string when the leftJoin do not match keys:
sapInvoices[0] mapObject (sItem, sKey) -> 
(sKey): ""

I am uncomfortable with these two points, and I believe that there are ways to improve this code, I just dont know how.

If there is a very different way of doing the same task, I also appreciate that kind of suggestion.

2 Answers

Give the following a try, if anything the code seems a bit simpler:

%dw 2.0
import * from dw::core::Arrays
output application/json

var mysqlInvoices = [
    {
        "id": 1,
        "owner": "Joseph"
    },
    {
        "id": 2,
        "owner": "Maria"
    }
]

var sapInvoices = [
    {
        "number": 3,
        "issuedBy": "XYZ"
    },
    {
        "number": 4,
        "issuedBy": "ABC"
    }
]

var fs2rn = {
    id: "identifier",
    owner: "ownerName"
}

var rightEmpty= {number:"",issuedBy:""}
---
leftJoin(
    // Do the field renaming at the very begining
    mysqlInvoices map ($ mapObject {(fs2rn[$$] default $$): $}), 
    sapInvoices, 
    (m) -> m.identifier, 
    (s) -> s.number
)
// Iterate over the results
// Get just the values, and colapse the objects into a single object
map (
    {($ pluck $)}
)
// Iterate over the results and use pattern-matching to 
// 
map (
    $ match {
        // Check if you have an id but not a number fields
        // In which case add the rightEmpty object
        case o if (o.identifier? and not (o.number?)) -> o ++ rightEmpty
        // Or give the object because you now have both an id and a number
        else o -> o
    }
)

The features and functions I used are:

If I was to give you an advice, it would be to better indent your code. Nonetheless, pretty good job!

Based on George's answer, you can remove pluck and match and directly combine left and right table. See below:

%dw 2.0
import * from dw::core::Arrays
output application/json

var mysqlInvoices = [
    {
        "id": 1,
        "owner": "Joseph"
    },
    {
        "id": 2,
        "owner": "Maria"
    }
]

var sapInvoices = [
    {
        "number": 3,
        "issuedBy": "XYZ"
    },
    {
        "number": 4,
        "issuedBy": "ABC"
    }
]

var fs2rn = {
    id: "identifier",
    owner: "ownerName"
}

var rightEmpty= {number:"",issuedBy:""}
---
leftJoin(
    // Do the field renaming at the very begining
    mysqlInvoices map ($ mapObject {(fs2rn[$$] default $$): $}), 
    sapInvoices, 
    (m) -> m.identifier, 
    (s) -> s.number
) map (item) -> item.l ++ (item.r default rightEmpty)
Related