skip to Main Content

I have two top level arrays: products and prices. I have to move all those price objects under product where price.productId == product.id. Note that there can be any number of products and prices and their relationships.

My current solution:

  1. copies all prices to every product
  2. tries to "remove" all those prices where ids don’t match

The problem is I can’t figure out how to match to the value of product.id in the step #2. In my example below I have hardcoded the value, see the FIXME comment.

I’m also open for better solutions if any.

Note also two TODO extra points (that might vanish with a more appropriate solution).

This is a simplified version of the actual problem to illustrate the point.

Input:

{
  "products": [
    {
      "id": "PROD_ID_1",
      "name": "Product 1"
    },
    {
      "id": "PROD_ID_2",
      "name": "Product 2"
    }
  ],
  "prices": [
    {
      "productId": "PROD_ID_1",
      "type": "PRICE_TYPE_1",
      "amount": "1.0"
    },
    {
      "productId": "PROD_ID_2",
      "type": "PRICE_TYPE_2",
      "amount": "2.0"
    },
    {
      "productId": "PROD_ID_1",
      "type": "PRICE_TYPE_3",
      "amount": "3.0"
    },
    {
      "productId": "PROD_ID_3",
      "type": "PRICE_TYPE_4",
      "amount": "4.0"
    }
  ]
}

Expected output:

{
  "products": [
    {
      "id": "PROD_ID_1",
      "name": "Product 1",
      "prices": [
        {
          "productId": "PROD_ID_1",
          "type": "PRICE_TYPE_1",
          "amount": "1.0"
        },
        {
          "productId": "PROD_ID_1",
          "type": "PRICE_TYPE_3",
          "amount": "3.0"
        }
      ]
    },
    {
      "id": "PROD_ID_2",
      "name": "Product 2",
      "prices": [
        {
          "productId": "PROD_ID_2",
          "type": "PRICE_TYPE_2",
          "amount": "2.0"
        }
      ]
    }
  ]
}

My Jolt spec:

[
  // copy all prices to every product
  {
    "operation": "shift",
    "spec": {
      "products": {
        "*": {
          "*": "products[&1].&",
          "@(2,prices)": "products[&1].prices"
        }
      }
    }
  },
  // remove prices where product.id != price.productId
  {
    "operation": "shift",
    "spec": {
      "products": {
        "*": { // iterate products array
          "*": "products[&1].&", // copy everything except prices
          "prices": {
            "*": { // iterate prices array
              "productId": { // value matching --- // copy only matching objects
                "PROD_ID_1": { // value        <-| // FIXME: should be product.id
                  "@(2)": "products[&5].prices[&3]"
                }
              }
            }
          }
        }
      }
    }
  }
  // TODO remove null objects from prices arrays
  // TODO remove price.productId as it's redundant at this point
]

The output of my Jolt spec:

{
  "products" : [ {
    "prices" : [ {
      "productId" : "PROD_ID_1",
      "type" : "PRICE_TYPE_1",
      "amount" : "1.0"
    }, null, {
      "productId" : "PROD_ID_1",
      "type" : "PRICE_TYPE_3",
      "amount" : "3.0"
    } ],
    "id" : "PROD_ID_1",
    "name" : "Product 1"
  }, {
    "prices" : [ {
      "productId" : "PROD_ID_1",
      "type" : "PRICE_TYPE_1",
      "amount" : "1.0"
    }, null, {
      "productId" : "PROD_ID_1",
      "type" : "PRICE_TYPE_3",
      "amount" : "3.0"
    } ],
    "id" : "PROD_ID_2",
    "name" : "Product 2"
  } ]
}

2

Answers


  1. You can use this spec:

    [
      {
        "operation": "shift",
        "spec": {
          "products": {
            "*": {
              "@": "&2.@(1,id)"
            }
          },
          "prices": {
            "*": {
              "@": "&2.@(1,productId)"
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "products": {
            "*": {
              "*": "&2.&1.&",
              "@(3,prices.&)": "&2.&1.prices"
            }
          }
        }
      },
      {
        "operation": "cardinality",
        "spec": {
          "*": {
            "*": {
              "prices": "MANY"
            }
          }
        }
      },
      {
        "operation": "shift",
        "spec": {
          "*": {
            "*": {
              "@": "&2[]"
            }
          }
        }
      }
    ]
    
    Login or Signup to reply.
  2. You can use the following spec

    [
      {// acuumulate the matching id values ( "products.id" vs. "prices.productId" ) 
       // under common nodes tagged by those id values
        "operation": "shift",
        "spec": {
          "prices": {
            "*": {
              "productId": {
                "*": { // returns "prices" array
                  "@2": "&.&4[]"
                },
                "@(3,products[&1])": "@0" // returns "id" & "name" attributes
              }
            }
          }
        }
      },
      { // pick objects up only having "id" attribute
        "operation": "shift",
        "spec": {
          "*": {
            "id": {
              "@1": "products[]"
            }
          }
        }
      }
    ]
    

    the demo on the site http://jolt-demo.appspot.com/ is

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search