How to loop and combine as one in Mule Dataweave

|▌冷眼眸甩不掉的悲伤 提交于 2020-06-16 17:57:08

问题


I have request of json and expected response one as mentioned below. It need to groupBy clientItemCode and i'm halfway somewhere stuck to loop around in same. Used both MapObject and reduce combination of function. Any help will be appreciated.

[
{
  "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"
 }
 ]

Expected Response:

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

回答1:


This is what I came up with, probably it could be simplified a little had I had more time to devote. Give it a try:

%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})
                    }
                }
            }
        }}
    }
}

I also made an assumption as I replicate in the comments: I assume that your data are ordered and all the records that will be From and To are paired with one another.

EDIT: Edited the code yet again in order to force the sorting of the ClientItemCode and then access each one of the values in order before all the transformations in creating result tags. The rest of the code is almost the same as before. Not sure why a simple orderBy did not work for you, it did for me.




回答2:


Assuming that the OPEN and/or CLOSED could be missing:

%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

            }
        } 
    )

Output:

<?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>


来源:https://stackoverflow.com/questions/62021682/how-to-loop-and-combine-as-one-in-mule-dataweave

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!