Search code examples
arraysjsonata

Creating 1-1 mapping of Array results


I am trying to use data coming back from an ElasticSearch query, and get it into an Array in jsonata in a certain format.

Essentially, I need my result set to be like this:

{
  "userName": [
    "[email protected]",
    "[email protected]",
    "[email protected]",
    "[email protected]"
  ],
  "label": [
    "Dealer",
    "Inquiry",
    "DD Test Skill1",
    "_11DavidTest"
  ],
  "value": [
    3,
    5,
    2,
    1
  ]
}

However, what I am getting is this:

{
  "userName": "[email protected]",
  "label": [
    "Dealer",
    "Inquiry",
    "DD Test Skill1",
    "_11DavidTest"
  ],
  "value": [
    3,
    5,
    2,
    1
  ]
}

I am using the following to map the results:

(
    $data := $map(data.hits.hits._source.item."Prod::User", function($v) {
        {

            "userName": $v.userName,
            "label": $v.userSkillLevels.skill.name,
            "value": $v.userSkillLevels.level
            
            
        }
    });

)

And my overall dataset returned form ElasticSearch is as follows:

{
  "data": {
    "took": 3,
    "timed_out": false,
    "_shards": {
      "total": 15,
      "successful": 15,
      "skipped": 0,
      "failed": 0
    },
    "hits": {
      "total": {
        "value": 2,
        "relation": "eq"
      },
      "max_score": 1.002851,
      "hits": [
        {
          "_index": "items_latest_production1_user",
          "_type": "_doc",
          "_id": "63d000766f67d40a73073d5d_f6144acf2b3ff31209ef9f6d461cd849",
          "_score": 1.002851,
          "_source": {
            "item": {
              "Prod::User": {
                "userSkillLevels": [
                  {
                    "level": 3,
                    "skill": {
                      "name": "Dealer"
                    }
                  },
                  {
                    "level": 5,
                    "skill": {
                      "name": "Inquiry"
                    }
                  },
                  {
                    "level": 2,
                    "skill": {
                      "name": "DD Test Skill1"
                    }
                  },
                  {
                    "level": 1,
                    "skill": {
                      "name": "_11DavidTest"
                    }
                  }
                ],
                "userName": "[email protected]"
              }
            }
          }
        }
      ]
    }
  }
}

I can see that each user that comes back from Elastic, then as all the skills/levels in an array associated to 1 username.

I need to have the same number of userNames, as their are skills ... and am struggling to get it just right.

Thoughts? Appreciate any help, I'm sure I'm overlooking something simple.

Actually, need this format:

[
{
"userName" : "[email protected]"
"label" : "Dealer"
"value" : 3
},
{
"userName" : "[email protected]"
"label" : "Inquiry"
"value" : 5
},
{
"userName" : "[email protected]"
"label" : "DD Test Skill"
"value" : 2
},
{
"userName" : "[email protected]"
"label" : "_11DavidTest"
"value" : 1
}
]

Solution

  • One way you could solve this is to create the userName array yourself and making sure it has the same length as userSkillLevels.skill, here's how you can do this:

    (
        $data := $map(data.hits.hits._source.item."Prod::User", function($v, $i, $a) {
            {
    
                "userName": $map([1..$count($v.userSkillLevels.skill)], function() {$v.userName}),
                "label": $v.userSkillLevels.skill.name,
                "value": $v.userSkillLevels.level
            }
        });
    )
    

    Feel free to check out this response in Stedi JSONata Playground: https://stedi.link/PVwGacu