2

The data object below contains information about products, customers & purchases.

const data = {
  products: [
    {
      id: "p01",
      name: "Bike Insurance",
    },
    {
      id: "p02",
      name: "Car Insurance",
    },
    {
      id: "p03",
      name: "Home Insurance",
    },
    {
      id: "p04",
      name: "Pet Insurance",
    },
  ],
  customers: [
    { id: "c01", firstname: "Rachel", lastname: "Jane" },
    { id: "c02", firstname: "Leilah", lastname: "Mandi" },
    { id: "c03", firstname: "Campbell", lastname: "Kendall" },
    { id: "c04", firstname: "Madonna", lastname: "Sammie" },
  ],
  purchases: [
    {
      customerId: "c01",
      purchases: [
        {
          productId: "p02",
          purchasedAt: "2021-08-03T00:00:00.000Z",
        },
        {
          productId: "p02",
          purchasedAt: "2021-08-04T00:00:00.000Z",
        },
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
      ],
    },
    {
      customerId: "c03",
      purchases: [
        {
          productId: "p04",
          purchasedAt: "2021-08-03T00:00:00.000Z",
        },
        {
          productId: "p04",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
        {
          productId: "p03",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
      ],
    },
    {
      customerId: "c02",
      purchases: [
        {
          productId: "p01",
          purchasedAt: "2021-09-12T00:00:00.000Z",
        },
      ],
    },
  ],
};

I have so far filtered out the customers who have made purchases by using the following code:

const customersWhoPurchased = data["customers"].filter((c) =>
  data["purchases"].find((p) => p.customerId === c.id)
)

so the customersWhoPurchased now looks like this:

[ { id: 'c01', firstname: 'Rachel', lastname: 'Jane' },
  { id: 'c02', firstname: 'Leilah', lastname: 'Mandi' },
  { id: 'c03', firstname: 'Campbell', lastname: 'Kendall' } ]

What is the reasoning finding a query to go through the purchases for each customer in the data object, checking productId in the purchases.purchases array and matching that up to the products and then returning the name of each product the customer has purchased and adding them into an additional key value pair in the customersWhoPurchased array, with the value being an array of each product name?

Result:

customers: [
  { id: "c01", firstname: "Rachel", lastname: "Jane", productNames: ['Bike Insurance', 'Car Insurance'] },
  { id: "c02", firstname: "Leilah", lastname: "Mandi", productNames: ['Bike Insurance'] },
  { id: "c03", firstname: "Campbell", lastname: "Kendall", productNames: ['Bike Insurance', 'Home Insurance', 'Pet Insurance'] },
],
philipxy
  • 14,867
  • 6
  • 39
  • 83
  • make a loop up so it is easier to get the names. `const productLookup = data.products.reduce((acc, item) => (acc[item.id] = item.name, acc), {});` Just have to do a map over the purchases. – epascarello May 05 '23 at 17:26
  • What's the specific issue you're having? You can either iterate the incoming `products` for each customers' purchases and gather product names, or load up a Map/object with product IDs => names and do the same thing for each customers' purchases. – Dave Newton May 05 '23 at 17:28
  • [Re relational querying.](https://stackoverflow.com/a/24425914/3404097) – philipxy May 16 '23 at 16:05

1 Answers1

1

First, I would create a hashtable-like structure for easy access:

const productsObj = data["products"].reduce((obj, item) => {
    obj[item.id] = item;
    return obj
},{});
// {"p01":{"id":"p01","name":"Bike Insurance"},"p02":{"id":"p02","name":"Car Insurance"},"p03":{"id":"p03","name":"Home Insurance"},"p04":{"id":"p04","name":"Pet Insurance"}}

const customersObj = data["customers"].reduce((obj, item) => {
    obj[item.id] = item;
    return obj
},{});
// {"c01":{"id":"c01","firstname":"Rachel","lastname":"Jane"},"c02":{"id":"c02","firstname":"Leilah","lastname":"Mandi"},"c03":{"id":"c03","firstname":"Campbell","lastname":"Kendall"},"c04":{"id":"c04","firstname":"Madonna","lastname":"Sammie"}}

Then, I would do something like this with the purchases, using the customer id as the key instead.

Consider that I am grouping purchases by the customer.

const purchasesGroupedByUser = data["purchases"].reduce((obj, item) => {
    // if first time finding this user
    if (!obj.hasOwnProperty(item.customerId)) {
        obj[item.customerId] = customersObj[item.customerId];
        obj[item.customerId].productNames = [];
    }

    const productNamesInCurrentPurchase = item.purchases.map(
        (product) => productsObj[product.productId].name
    );

    // updating productNames
    obj[item.customerId].productNames = obj[
        item.customerId
    ].productNames.concat(productNamesInCurrentPurchase);

    return obj;
}, {});
// {"c01":{"id":"c01","firstname":"Rachel","lastname":"Jane","productNames":["Car Insurance","Car Insurance","Bike Insurance","Bike Insurance"]},"c03":{"id":"c03","firstname":"Campbell","lastname":"Kendall","productNames":["Pet Insurance","Pet Insurance","Home Insurance","Bike Insurance"]},"c02":{"id":"c02","firstname":"Leilah","lastname":"Mandi","productNames":["Bike Insurance"]}}

And finally, convert to array:

const customersWithProductNames = Object.values(purchasesGroupedByUser);
// [{"id":"c01","firstname":"Rachel","lastname":"Jane","productNames":["Car Insurance","Car Insurance","Bike Insurance","Bike Insurance"]},{"id":"c03","firstname":"Campbell","lastname":"Kendall","productNames":["Pet Insurance","Pet Insurance","Home Insurance","Bike Insurance"]},{"id":"c02","firstname":"Leilah","lastname":"Mandi","productNames":["Bike Insurance"]}]