ang
ang

Reputation: 1581

How to denormalize data with primary and secondary key

I am trying to sort this normalized data set into orders with items starting at set_no = 0, line_no = 0.

With this function all the items are binned correctly, but set_no and line_no aren't updated.

let data = JSON.parse('[{"header":{"set_no":0},"line":{"line_no":2},"order":{"cart_id":"X1"}},{"header":{"set_no":4},"line":{"line_no":6},"order":{"cart_id":"X2"}},{"header":{"set_no":8},"line":{"line_no":10},"order":{"cart_id":"X1"}}]');

function denormalizeData(data) {

  let result = Object.values(                 // Index keys, starting with 0
      data.reduce((r, { order }, i, arr) => { // Push items to order, matching on unique cart_id
      let item = arr[i];
      r[order.cart_id] = (r[order.cart_id] || { order, items: [] });
      r[order.cart_id].items.push(item);
      return r;
    }, {})
  );

  console.log(JSON.stringify(result));

}

denormalizeData(data);

For example, in this case the goal would be to sort and update lines 0 and 1 for set 0, and line 0 for set 1.

How would I start at set_no = 0 and line_no = 0 when setting the new array and increment each accordingly when pushing new indices?

Expected output

[  
   {  
      "order":{  
         "cart_id":"X1"
      },
      "items":[  
         {  
            "header":{  
               "set_no":0
            },
            "line":{  
               "line_no":0
            }
         },
         {  
            "header":{  
               "set_no":0
            },
            "line":{  
               "line_no":1
            }
         }
      ]
   },
   {  
      "order":{  
         "cart_id":"X2"
      },
      "items":[  
         {  
            "header":{  
               "set_no":1
            },
            "line":{  
               "line_no":0
            }
         }
      ]
   }
]

Upvotes: 2

Views: 90

Answers (1)

alx
alx

Reputation: 2367

This could be the answer:

function denormalizeData(data) {

    let result = Object.values(                 // Index keys, starting with 0
        data.reduce((r, {order}, i, arr) => { // Push items to order, matching on unique cart_id
            let {header, line} = arr[i];
            let item = {header, line};
            r[order.cart_id] = (r[order.cart_id] || {order, items: []});
            r[order.cart_id].items.push(item);
            item.header.set_no = Object.keys(r).indexOf(order.cart_id);
            item.line.line_no = r[order.cart_id].items.length - 1;
            return r;
        }, {})
    );

    console.log(JSON.stringify(result, null, 4));
}

denormalizeData(data);

As you can see, line_no is really a number of items minus one in current order, so I use items.length - 1 there.

But set_no is a bit more complex, because order chunks can come unordered, that's why I get index of current order (some magic with object keys as this is not an array, but an object).

Also, I have removed stray order structure from output to match your example.

Upvotes: 2

Related Questions