Mulesoft dataweave внешнее соединение

#dataweave #mulesoft

#dataweave #mulesoft

Вопрос:

Нужна ваша помощь в преобразовании сообщения, подобного приведенному ниже, с помощью DataWeave 2.0.

Если у меня есть следующая полезная нагрузка JSON для пользователей и порядка. Необходимый вывод — это список пользователей, у которых есть заказы (внутреннее соединение), и пользователей, у которых нет заказов. Список не должен содержать данные пользователей, если у них есть заказы, которых нет в списке заказов.

Я пробовал использовать outerjoin из dataweave, но это приведет к тому, что пользователи, у которых есть заказ, также не присутствуют в списке заказов.

Пожалуйста, найдите пример ниже.

 var users = [
{
  "id": "1",
  "name": "Jerney",
  "order_id": "101",
},
{
  "id": "2",
  "name": "Marty"
  "order_id": "102",
},
{
  "id": "3",
  "name": "Marty"
}
]


var orders = [
{
   "order_id": "101",
   "product": "bread"
},
{
   "order_id": "104",
   "product": "broccoli"
}
 

]

Необходимый вывод

 [
{
  "id": "1",
  "name": "Jerney",
  "order_id": "101",
  "product": "bread"
}
{
  "id": "3",
  "name": "Marty"
}
]
 

Я надеюсь, что пример очистит ожидаемый результат. Я пробовал фильтровать (например, внешнее соединение), но оно также будет включать идентификатор заказа 102 во входных данных.

Спасибо за вашу помощь!

Ответ №1:

Я нашел способ добиться этого, но в моем тесте возникла какая-то странная проблема с отсутствием order_id в соединении, даже после его фильтрации. Я использовал дополнительную карту для обхода. Это не должно быть необходимо. Этот скрипт возвращает именно ваш желаемый результат.

 %dw 2.0
output application/json
import * from dw::core::Arrays
var users = [
    {
        "id": "1",
        "name": "Jerney",
        "order_id": "101"
    },
    {
        "id": "2",
        "name": "Marty",
        "order_id": "102"
    },
    {
        "id": "3",
        "name": "Marty"
    } 
]

var orders = [
    {
        "order_id": "101",
        "product": "bread"
    },
    {
        "order_id": "104",
        "product": "broccoli"
    }
]

fun getUserWithOrders(users) = (users filter $.order_id?) 
        map ($ mapObject ($):$) // for some reason had to add this to avoid a null error in the join

fun getUserWithoutOrders(users) = (users filter not $.order_id?) 
---
join(getUserWithOrders(users), orders, (u) -> u.order_id, (o) -> o.order_id)
    map ($.l    {product: $.r.product})
       getUserWithoutOrders(users)
 

Ответ №2:

Я предлагаю следующее (пояснения встроены в код):

 %dw 2.0
output application/json

var users = [
{
  "id": "1",
  "name": "Jerney",
  "order_id": "101",
},
{
  "id": "2",
  "name": "Marty",
  "order_id": "102",
},
{
  "id": "3",
  "name": "Marty"
}
]

var orders = [
{
   "order_id": "101",
   "product": "bread"
},
{
   "order_id": "104",
   "product": "broccoli"
}
]

import leftJoin from dw::core::Arrays

---
// Do a left outer join to get all data from the users in the output
leftJoin(
    users,
    orders,
    (u) -> u.order_id default "",
    (o) -> o.order_id default ""
)
// Iterate over the data and via pattern matching detect:
//   1. whether you have data in the l and the r nodes where 
//      you concatenate them and add them to the results
//   2. whether a sole l node has an order_id fields where
//      you add them to the result
//   3. throw aways all else
reduce (e,acc=[]) -> e match {
    case node if (node.l? and node.r?) -> acc   (node.l    node.r - "orderBy")
    case node if (node.l.order_id?) -> acc   node.l
    else node -> acc
}