如何在 Mule Dataweave 中作为一个循环和组合

How to loop and combine as one in Mule Dataweave

我有 json 的请求和如下所述的预期响应。它需要 groupBy clientItemCode 并且我在某个地方卡住了一半以相同的方式循环。同时使用 MapObjectreduce 组合函数。任何帮助将不胜感激。

[
{
  "ClientCode": "1",
  "ClientItemCode": "245",
  "LocationId": "CLOSED"
 },
 {
  "ClientCode": "1",
  "ClientItemCode": "245",
  "LocationId": "OPEN"
 },
    {
  "ClientCode": "2",
  "ClientItemCode": "245",
  "LocationId": "CHECKOUT"
 },
 {
  "ClientCode": "2",
  "ClientItemCode": "245",
  "LocationId": "TEST"
 },
 {
  "ClientCode": "1",
  "ClientItemCode": "123",
  "LocationId": "OPEN"
 },
 {
  "ClientCode": "1",
  "ClientItemCode": "123",
  "LocationId": "CLOSED"
 }
 ]

预期响应:

  <Results>
  <Result>
    <ClientItemCode>123<ClientItemCode>
    <ResultLines>
      <ResultLine>
        <ClientCode>1</ClientCode>
        <From>
          <LocationId>OPEN</LocationId>
        </From>
        <To>
          <LocationId>CLOSED</LocationId>
        </To>
      </ResultLine>
       <ResultLine>
        <ClientCode>2</ClientCode>
        <From>
          <LocationId>CHECKOUT</LocationId>
        </From>
        <To>
          <LocationId>TEST</LocationId>
        </To>
      </ResultLine>
    </ResultLines>
  </Result>
  <Result>
   <CientItemCode>245<ClientItemCode>
   <ResultLines>
      <ResultLine>
        <ClientCode>1</ClientCode>
        <From>
          <LocationId>CLOSED</LocationId>
        </From>
        <To>
          <LocationId>OPEN</LocationId>
        </To>
     </ResultLine>
    </ResultLines>
  </Result>
</Results>

假设 OPEN and/or CLOSED 可能丢失:

%dw 2.0
output application/xml
---
Results: payload groupBy $.ClientItemCode
    mapObject ((value, key, index) -> result: {
            ClientItemCode: key,
            ResultLines: {
                From: if (value.LocationId contains "OPEN") LocationId: "OPEN" else null,
                To: if (value.LocationId contains "CLOSED") LocationId: "CLOSED" else null

            }
        } 
    )

输出:

<?xml version='1.0' encoding='UTF-8'?>
<Results>
  <result>
    <ClientItemCode>245</ClientItemCode>
    <ResultLines>
      <From>
        <LocationId>OPEN</LocationId>
      </From>
      <To>
        <LocationId>CLOSED</LocationId>
      </To>
    </ResultLines>
  </result>
  <result>
    <ClientItemCode>123</ClientItemCode>
    <ResultLines>
      <From>
        <LocationId>OPEN</LocationId>
      </From>
      <To>
        <LocationId>CLOSED</LocationId>
      </To>
    </ResultLines>
  </result>
</Results>

这是我想出来的,如果我有更多时间投入,可能会稍微简化一下。试一试:

%dw 2.0
output application/xml
var data = [
 {
  "ClientCode": "1",
  "ClientItemCode": "245",
  "LocationId": "CLOSED"
 },
 {
  "ClientCode": "1",
  "ClientItemCode": "245",
  "LocationId": "OPEN"
 },
    {
  "ClientCode": "2",
  "ClientItemCode": "245",
  "LocationId": "CHECKOUT"
 },
 {
  "ClientCode": "2",
  "ClientItemCode": "245",
  "LocationId": "TEST"
 },
 {
  "ClientCode": "1",
  "ClientItemCode": "123",
  "LocationId": "OPEN"
 },
 {
  "ClientCode": "1",
  "ClientItemCode": "123",
  "LocationId": "CLOSED"
 }
]
---
// I assume that your data are ordered and all the records that will be From and To
// are paired with one another. It is doable without making such assumption but the
// algorithm will get complex.
results: do {
    // Group by the data
    var groupedData = data map {($),(From: true) if (isEven($$))} groupBy $.ClientItemCode
    // Order the client Ids
    var orderedClientIds = groupedData pluck $$ orderBy $ as Number
    ---
    orderedClientIds reduce (cId, results={}) -> do {
        var clientItemCode = cId
        var groupedByClientICode = groupedData[cId] groupBy $.ClientCode pluck $
        ---
        results ++ {result: {
            ClientItemCode: clientItemCode,
            ResultLines: groupedByClientICode reduce (cliCode, lines={}) -> do {
                var clientCode = cliCode[0].ClientCode
                ---
                lines ++ {
                    ClientCode: clientCode,
                    ResultLine: cliCode reduce (e, acc={}) -> do {
                        var locRec = {LocationId: e.LocationId}
                        ---
                        acc ++ (if (e.From?) {From: locRec } else {To: locRec})
                    }
                }
            }
        }}
    }
}

我在评论中复制时也做了一个假设:我假设你的数据是有序的,所有 FromTo 的记录都相互配对。

编辑:再次编辑代码以强制对 ClientItemCode 进行排序,然后在创建 result 标签的所有转换之前按顺序访问每个值。其余代码与之前几乎相同。不确定为什么一个简单的 orderBy 对你不起作用,但它对我有用。