Dataweave - Как преобразовать массив элементов в родительско-дочернее отношение в Dataweave

Я хочу преобразовать приведенный ниже ввод в вывод JSON родитель-потомок с помощью преобразования dataweave. Пожалуйста, дайте мне знать, работал ли кто-нибудь над этим раньше. Ниже я добавил образец ввода и вывода json.

Обновленный пост с дополнительными узлами: мне нужно несколько родительских узлов с уровнем местоположения = 1 с соответствующими иерархиями.

Входной формат json:

[
    {
        "ENTITY_ID": 1,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "123"
    },
    {
        "ENTITY_ID": 2,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 2,
        "LOCATION_CODE": "234"
    },
    {
        "ENTITY_ID": 3,
        "PARENT_EID": 2,
        "LOCATION_LEVEL": 3,
        "LOCATION_CODE": "345"
    },
    {
        "ENTITY_ID": 4,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 2,
        "LOCATION_CODE": "567"
    },
    {
        "ENTITY_ID": 5,
        "PARENT_EID": 5,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "012"
    },
    {
        "ENTITY_ID": 6,
        "PARENT_EID": 5,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "023"
    }
]

Формат вывода json:

[
    {
        "ENTITY_ID": 1,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "123",
        "CHILDRENS":[
                {
                    "ENTITY_ID": 2,
                    "PARENT_EID": 1,
                    "LOCATION_LEVEL": 2,
                    "LOCATION_CODE": "234"
                    "CHILDRENS":[{
                            "ENTITY_ID": 3,
                            "PARENT_EID": 2,
                            "LOCATION_LEVEL": 3,
                            "LOCATION_CODE": "345"                          
                    }]
                },
                {
                    "ENTITY_ID": 4,
                    "PARENT_EID": 1,
                    "LOCATION_LEVEL": 2,
                    "LOCATION_CODE": "567"
                }
        ]
        
    },
    {
        "ENTITY_ID": 5,
        "PARENT_EID": 5,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "012",
        "CHILDRENS":[{
                  "ENTITY_ID": 6,
                  "PARENT_EID": 5,
                  "LOCATION_LEVEL": 2,
                  "LOCATION_CODE": "023"
              }]
    }
]

person Sandesh patil    schedule 23.12.2020    source источник


Ответы (1)


Попробуйте:

%dw 2.0
output application/json

var data = [
    {
        "ENTITY_ID": 1,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "123"
    },
    {
        "ENTITY_ID": 2,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 2,
        "LOCATION_CODE": "234"
    },
    {
        "ENTITY_ID": 3,
        "PARENT_EID": 2,
        "LOCATION_LEVEL": 3,
        "LOCATION_CODE": "345"
    },
    {
        "ENTITY_ID": 4,
        "PARENT_EID": 1,
        "LOCATION_LEVEL": 2,
        "LOCATION_CODE": "567"
    },
    {
        "ENTITY_ID": 5,
        "PARENT_EID": 5,
        "LOCATION_LEVEL": 1,
        "LOCATION_CODE": "012"
    },
    {
        "ENTITY_ID": 6,
        "PARENT_EID": 5,
        "LOCATION_LEVEL": 2,
        "LOCATION_CODE": "023"
    }
]

var top = data filter ($.LOCATION_LEVEL == 1)

fun insert(t,e) = t match {
    case {} -> e
    case tree if (tree.ENTITY_ID == e.PARENT_EID) -> do {
        var node = tree - "CHILDREN"
        var children = if (tree.CHILDREN?) (tree.CHILDREN + e) else [e]
        ---
        {(node),CHILDREN: children}
    }
    case tree if (tree.ENTITY_ID != e.PARENT_EID) -> do {
        var node = tree - "CHILDREN"
        var children = tree.CHILDREN map ($ insert e)
        ---
        {(node), (CHILDREN: children) if (not isEmpty(children))}
    }
    else -> $
}


---
top map (topnode) -> (
    (data -- top) orderBy $.ENTITY_ID reduce ((e, acc=topnode) -> acc insert e)
) 

Протестируйте его с большим количеством входных данных, и вам может потребоваться скорректировать код, если некоторые другие тестовые примеры не пройдут.

Вы (или, может быть, кто-то другой) можете захотеть переписать это, используя оператор update, по сравнению с построением переменных node и children, как это делаю я.

person George    schedule 25.12.2020
comment
Он работает до 8 уровней дочерних узлов. однако, когда я пытаюсь вставить дочерний узел для 4-го родителя, это не удается. Спасибо за ответ, это очень много значит - person Sandesh patil; 28.12.2020
comment
Изолируйте запись, которая вызывает проблему, затем изучите ее и воспроизведите поведение в ваших образцах данных. Также будет полезно, если вы предоставите полученное сообщение об ошибке. - person George; 30.12.2020
comment
В случае повторного запуска с location_level 1 означает новую иерархию, такой тип senario не работает как новый уровень Location 1 - person Sandesh patil; 31.12.2020
comment
Что делать, если у меня есть еще один узел уровня местоположения 1, как показано ниже {ENTITY_ID: 2, PARENT_EID: 2, LOCATION_LEVEL: 1, LOCATION_CODE: 156} - person Sandesh patil; 02.01.2021
comment
Хорошо, поэтому мы не будем ходить туда-сюда, вам нужно предоставить образцы данных, которые фиксируют все перестановки. Затем вам нужно изменить исходное сообщение, чтобы оно содержало образцы данных. Кроме того, вы ДОЛЖНЫ предоставить алгоритмические детали (т.е. логику) того, как вы связываете родительские и дочерние узлы. Тогда и только тогда я смогу оказать дальнейшую помощь. - person George; 02.01.2021
comment
Только что обновил мой вопрос с дополнительными узлами. Спасибо за ваш ответ - person Sandesh patil; 06.01.2021
comment
Обратите внимание, что при использовании выражения dataweave я не получаю массив иерархических данных, как в скобках []. Его в скобках: {}. Спасибо еще раз :) - person Sandesh patil; 06.01.2021
comment
Также обратите внимание, что это образцы данных. Фактические данные содержат около 5000 списков узлов, которые я преобразовываю. Я получаю ошибку Java.lang.stackoverflow. Есть ли способ это оптимизировать? - person Sandesh patil; 06.01.2021
comment
Что касается логики, она основана исключительно на отношениях родительского идентификатора и идентификатора объекта, а также на уровне местоположения. Если уровень местоположения = 1, то его родительский узел - person Sandesh patil; 06.01.2021
comment
Ты там Джордж? - person Sandesh patil; 08.01.2021
comment
Да, я Сандеш, но я занят на этой неделе - возможно, я посмотрю на него в выходные. - person George; 08.01.2021
comment
Пожалуйста, дважды проверьте свои образцы данных - кажется, что последняя запись должна иметь LOCATION_LEVEL: 2 - person George; 09.01.2021
comment
Внесены обновления в решение, чтобы отразить ваши последние образцы данных. Если код по-прежнему не работает с вашими данными из реального мира, скорее всего, вам не хватает дальнейших перестановок ваших данных, и я считаю, что дал вам довольно хорошее преимущество;) - person George; 09.01.2021