合并对象数组,当匹配条件满足时。

huangapple go评论62阅读模式
英文:

Combine arrays of objects when matching criteria is fullfilled

问题

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"
  } ]
}
英文:

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:

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

Expected output:

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

My Jolt spec:

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

The output of my Jolt spec:

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

答案1

得分: 1

你可以使用这个规范:

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

注意:上述代码已经将HTML实体编码的字符解码为正常的JSON格式。

英文:

You can use this spec:

[
  {
    &quot;operation&quot;: &quot;shift&quot;,
    &quot;spec&quot;: {
      &quot;products&quot;: {
        &quot;*&quot;: {
          &quot;@&quot;: &quot;&amp;2.@(1,id)&quot;
        }
      },
      &quot;prices&quot;: {
        &quot;*&quot;: {
          &quot;@&quot;: &quot;&amp;2.@(1,productId)&quot;
        }
      }
    }
  },
  {
    &quot;operation&quot;: &quot;shift&quot;,
    &quot;spec&quot;: {
      &quot;products&quot;: {
        &quot;*&quot;: {
          &quot;*&quot;: &quot;&amp;2.&amp;1.&amp;&quot;,
          &quot;@(3,prices.&amp;)&quot;: &quot;&amp;2.&amp;1.prices&quot;
        }
      }
    }
  },
  {
    &quot;operation&quot;: &quot;cardinality&quot;,
    &quot;spec&quot;: {
      &quot;*&quot;: {
        &quot;*&quot;: {
          &quot;prices&quot;: &quot;MANY&quot;
        }
      }
    }
  },
  {
    &quot;operation&quot;: &quot;shift&quot;,
    &quot;spec&quot;: {
      &quot;*&quot;: {
        &quot;*&quot;: {
          &quot;@&quot;: &quot;&amp;2[]&quot;
        }
      }
    }
  }
]

答案2

得分: 1

以下是翻译好的部分:

你可以使用以下规范

[
  {// 累积匹配的 id 值("products.id" vs. "prices.productId")
   // 在由这些 id 值标记的公共节点下
    "operation": "shift",
    "spec": {
      "prices": {
        "*": {
          "productId": {
            "*": { // 返回 "prices" 数组
              "@2": "&.4[]"
            },
            "@(3,products[&1])": "@0" // 返回 "id" & "name" 属性
          }
        }
      }
    }
  },
  { // 仅提取具有 "id" 属性的对象
    "operation": "shift",
    "spec": {
      "*": {
        "id": {
          "@1": "products[]"
        }
      }
    }
  }
]

在网站 http://jolt-demo.appspot.com/ 上的 演示 如下图所示
合并对象数组,当匹配条件满足时。

英文:

You can use the following spec

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

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

合并对象数组,当匹配条件满足时。

huangapple
  • 本文由 发表于 2023年5月10日 13:44:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215226.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定