Home > Back-end >  How do I avoid creating a cross product when extracting multiple sub-elements from a list in JQ?
How do I avoid creating a cross product when extracting multiple sub-elements from a list in JQ?

Time:11-16

I'm getting product information from a vendor. It's got a bajillion fields in it, but I have this trimmed down to just relevant fields. I'm anticipating the solution has something to do with map(), but I just haven't been able to wrap my head around it.

When I try and get multiple fields out of a sub-dictionary, it does a cross product. I'm expecting 2 lines back in this example, but I get 4.

Fiddle
Expected output:

{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_A",
  "img_angle": "ViewA"
}
{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_B",
  "img_angle": "ViewB"
}

Starting data:

{
  "Products": [
    {
      "SKU": "1234",
      "Description": "Pink Ring",
      "RingSize": 7,
      "Images": [
        {
          "FullUrl": "https://provider.com/rings/1234_A",
          "SortOrder": 1,
          "Angle": "ViewA"
        },
        {
          "FullUrl": "https://provider.com/rings/1234_B",
          "SortOrder": 2,
          "Angle": "ViewB"
        }
      ]
    }
  ]
}

I then pass it through this filter:

.Products[] | { sku: .SKU, desc: .Description, img_url: .Images[].FullUrl, img_angle: .Images[].Angle }

This gives me the following data:

{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_A",
  "img_angle": "ViewA"
}
{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_A",
  "img_angle": "ViewB"
}
{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_B",
  "img_angle": "ViewA"
}
{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_B",
  "img_angle": "ViewB"
}

This is what I'm hoping for. You can see URL_A and ANGLE_A don't cross multiply with URL_B and ANGLE_B.

{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_A",
  "img_angle": "ViewA"
}
{
  "sku": "1234",
  "desc": "Pink Ring",
  "img_url": "https://provider.com/rings/1234_B",
  "img_angle": "ViewB"
}

Please don't assume that you can trust img_url and img_angle to have values that reference each other - you definitely can't, that's only here for illustration purposes.

I've tried several things that keep giving me a cross product and don't actually change the output, like { sku: .SKU, desc: .Description } { img_url: .Images[].FullUrl } { img_angle: .Images[].Angle }.

I've also tried adapting recipes from this recipe book and this cheat sheet. I haven't been able to get anything useful that doesn't puke at runtime.

CodePudding user response:

Is this what you are looking for:

.Products[] | {sku: .SKU, desc: .Description}   (
  .Images[] | {img_url: .FullUrl, img_angle: .Angle}
)

Fiddle

  • Related