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