从数组中使用DataWeave派生父子层次结构(附加细节)

huangapple go评论68阅读模式
英文:

Derive parent-child hierarchy from an array using DataWeave (additional details)

问题

这是对先前问题的跟进。感谢@harshank的快速帮助。我将此问题单独发布,因为需要额外的检查,这在先前的问题中我没有提到。因此,先前发布的解决方案适用于所述要求。

我在此添加了额外的要求:

  1. 决定gpparent是否匹配取决于额外的属性eye_colour(请参见下面的示例有效负载)。

  2. 在响应中还需要填充额外的字段(在先前的问题中没有提到)。像nameeye_colour之类的东西。

所以,例如,这是有效负载:

[
  {
    "gp": "T1",
    "gp_eye_colour": "blue",
    "gp_name" : "John",
    "parent": "T1",
    "parent_eye_colour" : "black",
    "parent_name" : "Sam",
    "child": "C1",
    "child_eye_colour" : "brown",
    "child_name" : "C1"
  },
 {
    "gp": "T1",
    "gp_eye_colour": "blue",
    "gp_name" : "John",
    "parent": "T1",
    "parent_eye_colour" : "black",
    "parent_name" : "Sam",
    "child": "C1",
    "child_eye_colour" : "brown",
    "child_name" : "C1"
  }
]

现在,使用先前的解决方案,我尝试构建如下:

%dw 2.0
output application/xml
// 层次结构的结构。比如,如果你添加了一个"grand child",它应该能够工作(尽管我还没有测试过这一点)
var hierarchy = {
    gp: {
        parent: {
            child: null
        }
    }
}
fun getDirectGeanologies(records, hierarchyStructure,isGp,isParent,isChild) = do {
    var topLevel = keysOf(hierarchyStructure)[0] as String
    var secondLevel = keysOf(hierarchyStructure[topLevel])[0]
    ---
    (records groupBy $[topLevel])
        mapObject ((level1Childs, code) -> 
            genealogy: {
                code: code,
                eye_colour: if(isGp) (level1Childs.gp_eye_colour) else if(isParent) (level1Childs.parent_eye_colour) else (level1Childs.child_eye_colour),
                name: if(isGp) (level1Childs.gp_name) else if(isParent) (level1Childs.parent_name) else (level1Childs.child_name),
                hierarchy:
                    if(secondLevel != null) // 如果没有更多的子元素,什么也不做。
                        (level1Childs groupBy ((item) -> item[secondLevel] ~= code) // 这是为了处理当parent = gp的情况
                            mapObject ((value, hasSameParent) -> 
                                // 如果parent = gp,我们希望跳过parent,直接链接到child
                                if(hasSameParent as Boolean) getDirectGeanologies(value, hierarchyStructure[topLevel][secondLevel],false,false,true) 
                                // 递归调用带有子记录的函数,并沿着hierarchyStructure向下移动一个级别
                                else getDirectGeanologies(value, hierarchyStructure[topLevel],false,true,false) 
                        ))
                    else {}
            }
        )
}

---
list: getDirectGeanologies(payload,hierarchy,true,false,false)

然而,它会生成重复的eye_colourname元素。理想情况下,它应该只打印值一次,值应该是gp / parent / child中的一个。

这是期望的响应:

<?xml version='1.0' encoding='UTF-8'?>
<list>
  <genealogy>
    <code>T1</code>
    <eye_colour>blue</eye_colour>
    <name>John</name>
    <hierarchy>
      <genealogy>
        <code>C1</code>
        <eye_colour>brown</eye_colour>
        <name>C1</name>
        <hierarchy/>
      </genealogy>
    </hierarchy>
  </genealogy>
</list>

我还没有弄清如何检查gp和parent是否基于两个字段(gp & gp_eye_colourparent & parent_eye_colour)具有相同的值。

感谢@sudhish_s的回复,我添加了一个示例,详细说明了何时跳过parent(当gp和parent的gp & gp_eye_colour相同时)。

示例输入:(这里,parent "Sam" 不应被跳过,因为尽管gp和parent相同,但他们的眼睛颜色不同。类似地,在"Don"的情况下,应该跳过此parent,因为gp和parent及其眼睛颜色都相同)。

[
  {
    "gp": "T1",
    "gp_eye_colour": "blue",
    "gp_name" : "John",
    "parent": "T1",
    "parent_eye_colour" : "black",
    "parent_name" : "Sam",
    "child": "C1",
    "child_eye_colour" : "brown",
    "child_name" : "C1"
  },
 {
    "gp": "T1",
    "gp_eye_colour": "blue",
    "gp_name" : "John",
    "parent": "T1",
    "parent_eye_colour" : "blue",
    "parent_name" : "Don",
    "child": "C1",
    "child_eye_colour" : "brown",
    "child_name" : "C1"
  }  
]

这是期望的响应:

<?xml version='1.0' encoding='UTF-8'?>
<list>
  <genealogy>
    <code>T1</code>
    <eye_colour>blue</eye_colour>
    <name>John</name>
    <hierarchy>
      <genealogy>
        <code>T1</code>
        <eye_colour>black</eye_colour>
        <name>Sam</name>
        <hierarchy>
          <genealogy>
            <code>C1</code>
            <eye_colour>brown</eye_colour>
            <name>C1</name>
            <hierarchy/>
          </genealogy>
        </hierarchy>
      </genealogy>
     

<details>
<summary>英文:</summary>

This is a follow up to an [earlier][1] question. Thanks @harshank for the quick help. I am posting this question separately since there was an additional check required which I had not asked in the earlier question. So, the solution posted earlier works fine for the stated requirement.

I am adding the additional requirement here:
1. The decision if ```gp``` and ```parent``` match depends on an additional attribute ```eye_colour``` (please see sample payload below).

2. Also in the response additional fields need to be populated (which was not mentioned in the earlier question). Things like ```name``` and ```eye_colour```.

So, as an example this is the payload:

```json
[
  {
    &quot;gp&quot;: &quot;T1&quot;,
    &quot;gp_eye_colour&quot;: &quot;blue&quot;,
    &quot;gp_name&quot; : &quot;John&quot;,
    &quot;parent&quot;: &quot;T1&quot;,
    &quot;parent_eye_colour&quot; : &quot;black&quot;,
    &quot;parent_name&quot; : &quot;Sam&quot;,
    &quot;child&quot;: &quot;C1&quot;,
    &quot;child_eye_colour&quot; : &quot;brown&quot;,
    &quot;child_name&quot; : &quot;C1&quot;

  },
 {
    &quot;gp&quot;: &quot;T1&quot;,
    &quot;gp_eye_colour&quot;: &quot;blue&quot;,
    &quot;gp_name&quot; : &quot;John&quot;,
    &quot;parent&quot;: &quot;T1&quot;,
    &quot;parent_eye_colour&quot; : &quot;black&quot;,
    &quot;parent_name&quot; : &quot;Sam&quot;,
    &quot;child&quot;: &quot;C1&quot;,
    &quot;child_eye_colour&quot; : &quot;brown&quot;,
    &quot;child_name&quot; : &quot;C1&quot;

  }
  
]

And now using the earlier solution, I have tried to build on top of it as:

%dw 2.0
output application/xml
// hierarchy&#39;s structure. If, lets say you add a &quot;grand child&quot; it should work. (haven&#39;t tested this though)
var hierarchy = {
    gp: {
        parent: {
            child: null
        }
    }
}
fun getDirectGeanologies(records, hierarchyStructure,isGp,isParent,isChild) = do {
    var topLevel = keysOf(hierarchyStructure)[0] as String
    var secondLevel = keysOf(hierarchyStructure[topLevel])[0]
    ---
    (records groupBy $[topLevel])
        mapObject ((level1Childs, code) -&gt; 
            genealogy: {
                code: code,
                eye_colour: if(isGp) (level1Childs.gp_eye_colour) else if(isParent) (level1Childs.parent_eye_colour) else (level1Childs.child_eye_colour),
                name: if(isGp) (level1Childs.gp_name) else if(isParent) (level1Childs.parent_name) else (level1Childs.child_name),
                hierarchy:
                    if(secondLevel != null) // If there are no more childs, do nothing.
                        (level1Childs groupBy ((item) -&gt; item[secondLevel] ~= code) // This is to handle when parent = gp
                            mapObject ((value, hasSameParent) -&gt; 
                                // If parent = gp, we want to skip parent and link directly to child
                                if(hasSameParent as Boolean) getDirectGeanologies(value, hierarchyStructure[topLevel][secondLevel],false,false,true) 
                                // recurrsively call the function with child records and going down the hierarchyStructure by one
                                else getDirectGeanologies(value, hierarchyStructure[topLevel],false,true,false) 
                        ))
                    else {}
            }
        )
}

---
list: getDirectGeanologies(payload,hierarchy,true,false,false)

However, it is generating duplicate elements for eye_colour and name. Ideally, it should print the values only once with the value of either gp / parent / child.

This is the expected response:

&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;
&lt;list&gt;
  &lt;genealogy&gt;
    &lt;code&gt;T1&lt;/code&gt;
    &lt;eye_colour&gt;blue&lt;/eye_colour&gt;
    &lt;name&gt;John&lt;/name&gt;
    &lt;hierarchy&gt;
      &lt;genealogy&gt;
        &lt;code&gt;C1&lt;/code&gt;
        &lt;eye_colour&gt;brown&lt;/eye_colour&gt;
        &lt;name&gt;C1&lt;/name&gt;
        &lt;hierarchy/&gt;
      &lt;/genealogy&gt;
    &lt;/hierarchy&gt;
  &lt;/genealogy&gt;
&lt;/list&gt;

I was also not able to figure out how to check if gp and parent have same values based on two fields (gp &amp; gp_eye_colour vs parent &amp; parent_eye_colour)

Thank you @sudhish_s for the response, adding an example to elaborate regarding decision of when to skip parent (when gp &amp; gp_eye_colour of gp are same as parent &amp; parent_eye_colour of parent).

Sample input: (Here parent Sam should not be skipped since though gp and parent are same their eye colours are different. Similarly, in case of Don, this parent should be skipped since gp and parent and their eye colours are the same).

[
  {
    &quot;gp&quot;: &quot;T1&quot;,
    &quot;gp_eye_colour&quot;: &quot;blue&quot;,
    &quot;gp_name&quot; : &quot;John&quot;,
    &quot;parent&quot;: &quot;T1&quot;,
    &quot;parent_eye_colour&quot; : &quot;black&quot;,
    &quot;parent_name&quot; : &quot;Sam&quot;,
    &quot;child&quot;: &quot;C1&quot;,
    &quot;child_eye_colour&quot; : &quot;brown&quot;,
    &quot;child_name&quot; : &quot;C1&quot;

  },
 {
    &quot;gp&quot;: &quot;T1&quot;,
    &quot;gp_eye_colour&quot;: &quot;blue&quot;,
    &quot;gp_name&quot; : &quot;John&quot;,
    &quot;parent&quot;: &quot;T1&quot;,
    &quot;parent_eye_colour&quot; : &quot;blue&quot;,
    &quot;parent_name&quot; : &quot;Don&quot;,
    &quot;child&quot;: &quot;C1&quot;,
    &quot;child_eye_colour&quot; : &quot;brown&quot;,
    &quot;child_name&quot; : &quot;C1&quot;
  }  
]

Here is the expected response:

&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;
&lt;list&gt;
  &lt;genealogy&gt;
    &lt;code&gt;T1&lt;/code&gt;
    &lt;eye_colour&gt;blue&lt;/eye_colour&gt;
    &lt;name&gt;John&lt;/name&gt;
    &lt;hierarchy&gt;
      &lt;genealogy&gt;
        &lt;code&gt;T1&lt;/code&gt;
        &lt;eye_colour&gt;black&lt;/eye_colour&gt;
        &lt;name&gt;Sam&lt;/name&gt;
        &lt;hierarchy&gt;
          &lt;genealogy&gt;
            &lt;code&gt;C1&lt;/code&gt;
            &lt;eye_colour&gt;brown&lt;/eye_colour&gt;
            &lt;name&gt;C1&lt;/name&gt;
            &lt;hierarchy/&gt;
          &lt;/genealogy&gt;
        &lt;/hierarchy&gt;
      &lt;/genealogy&gt;
      &lt;genealogy&gt;
        &lt;code&gt;C1&lt;/code&gt;
        &lt;eye_colour&gt;brown&lt;/eye_colour&gt;
        &lt;name&gt;C1&lt;/name&gt;
        &lt;hierarchy/&gt;
      &lt;/genealogy&gt;
    &lt;/hierarchy&gt;
  &lt;/genealogy&gt;
&lt;/list&gt;

答案1

得分: 1

以下是您要翻译的部分:

Slightly different version. Used arrays for reference.

%dw 2.0
output application/xml
var hierarchy = ["gp", "parent", "child"]
fun getDirectGeanologies(records, level) = do {
    var hLevel = hierarchy[level]
    ---
    records groupBy $[hLevel] mapObject ((children, code) -&gt; 
        genealogy: {
            code: code,
            eye_colour: children[0][hLevel ++ "eye_colour"],
            name: children[0][hLevel ++ "name"],
            hierarchy: 
                if (level == sizeOf(hierarchy) - 1) {}
                else do {
                    var nextLevel = level + 1
                    var nextGen = children groupBy ($[hierarchy[nextLevel]])
                    --- 
                    nextGen mapObject ((nextGenChildren, nextGenCode) -&gt; 
                        if (nextGenCode == code)
                            getDirectGeanologies (nextGenChildren, nextLevel + 1 )
                        else
                            getDirectGeanologies (nextGenChildren, nextLevel)
                    )                   
                }
                                            
        }
    )
}
---
list: getDirectGeanologies(payload,0)

The issue with elements appear multiple times is due to the level1Childs is Array. Change the output to json, it will be more clear. If you want to use your code, change the eye_colour and name mapping to below

                eye_colour: if(isGp) (level1Childs[0].gp_eye_colour) else if(isParent) (level1Childs[0].parent_eye_colour) else (level1Childs[0].child_eye_colour),
                name: if(isGp) (level1Childs[0].gp_name) else if(isParent) (level1Childs[0].parent_name) else (level1Childs[0].child_name),
英文:

Slightly different version. Used arrays for reference.

%dw 2.0
output application/xml
var hierarchy = [&quot;gp&quot;, &quot;parent&quot;, &quot;child&quot;]
fun getDirectGeanologies(records, level) = do {
    var hLevel = hierarchy[level]
    ---
    records groupBy $[hLevel] mapObject ((children, code) -&gt; 
        genealogy: {
            code: code,
            eye_colour: children[0][hLevel ++ &quot;_eye_colour&quot;],
            name: children[0][hLevel ++ &quot;_name&quot;],
            hierarchy: 
                if (level == sizeOf(hierarchy) - 1) {}
                else do {
                    var nextLevel = level + 1
                    var nextGen = children groupBy ($[hierarchy[nextLevel]])
                    --- 
                    nextGen mapObject ((nextGenChildren, nextGenCode) -&gt; 
                        if (nextGenCode == code)
                            getDirectGeanologies (nextGenChildren, nextLevel + 1 )
                        else
                            getDirectGeanologies (nextGenChildren, nextLevel)
                    )                   
                }
                                            
        }
    )
}
---
list: getDirectGeanologies(payload,0)

The issue with elements appear multiple times is due to the level1Childs is Array. Change the output to json, it will be more clear. If you want to use your code, change the eye_colour and name mapping to below

                eye_colour: if(isGp) (level1Childs[0].gp_eye_colour) else if(isParent) (level1Childs[0].parent_eye_colour) else (level1Childs[0].child_eye_colour),
                name: if(isGp) (level1Childs[0].gp_name) else if(isParent) (level1Childs[0].parent_name) else (level1Childs[0].child_name),

huangapple
  • 本文由 发表于 2023年2月6日 19:43:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75360870.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定