How to format this association fetching sequelize

Viewed 149

I have an association many to many with two tables, products and orders. In my pivot table i save the id, quantity and price of the product. When I fetch the product i need the name of this product, but to get the name I need to get in the product table. The response of my fetching return like this

{
    "id": 111,
    "name": "Matheus",
    "phonenumber": "69993750103",
    "reference": null,
    "value_subtotal": "10.000",
    "value_delivery": "5.000",
    "value_total": "15.000",
    "status": "pending",
    "products": [
        {
            "name": "Açai 350ml",
            "OrdersProducts": {
                "quantity": 2,
                "price": "0.000"
            }
        },
        {
            "name": "acai 350ml",
            "OrdersProducts": {
                "quantity": 3,
                "price": "0.000"
            }
        }
    ]
}

but i need the json in this format

{
    "id": 111,
    "name": "Matheus",
    "street": "Rua olavo bilac",
    "phonenumber": "69993750103",
    "number": "3511",
    "reference": null,
    "note": "Retirar o morango",
    "value_subtotal": "10.000",
    "value_delivery": "5.000",
    "value_total": "15.000",
    "status": "pending",
    "createdAt": "2021-10-20T18:26:25.000Z",
    "updatedAt": "2021-10-20T18:26:25.000Z",
    "products": [
        {
            "name": "Açai 350ml",
            // here the difference, i want create a single object in the return, with all data i need of the product
            "quantity": 2,
            "price": "0.000"
            }
        },
        {
            "name": "acai 350ml",
            "quantity": 3,
            "price": "0.000"
            
        }
    ]
}

My controller

 async getOrder(req, res) {
        const { id } = req.params;

        const order = await Orders.findByPk(id, {include: [{
            association: 'products',
            attributes: ['name'],
            through: {
                attributes:['quantity', 'price'],
                
                
            },
            raw: true,
        }]})
        if (!order) return res.status(404).send({ message: 'order ${`id`}' })
        return res.json(order);
    },

3 Answers

Maybe you can implement the query without the association but using model.

 async getOrder(req, res) {
    const { id } = req.params;

    const order = await Orders.findByPk(id, {include: [{
        model: Product,
        attributes: ['name'],
        include: [{
            association: "OrdersProducts",
            attributes:['quantity', 'price'], 
            raw: true,
        }],
    }]})
    if (!order) return res.status(404).send({ message: 'order ${`id`}' })
    return res.json(order);
},

You will still get order.quantity and order.price as a name at product as properties.

var a = {
  "id": 111,
  "name": "Matheus",
  "phonenumber": "69993750103",
  "reference": null,
  "value_subtotal": "10.000",
  "value_delivery": "5.000",
  "value_total": "15.000",
  "status": "pending",
  "products": [{
      "name": "Açai 350ml",
      "OrdersProducts": {
        "quantity": 2,
        "price": "0.000"
      }
    },
    {
      "name": "acai 350ml",
      "OrdersProducts": {
        "quantity": 3,
        "price": "0.000"
      }
    }
  ]
};

var orders = [];
orders.push(a);

var updatedOrders = orders.map(function(order) {
  order.products.forEach(function(product) {
    product.price = product.OrdersProducts.price;
    product.quantity = product.OrdersProducts.quantity;
    delete product.OrdersProducts;
  });
  return order;
});
console.log(updatedOrders);

If you have control over the order and/or product object, you can add custom toJSON method. You can format the json output away you want. https://futurestud.io/tutorials/create-a-custom-tojson-function-in-node-js-and-javascript

If you do not have control of the object, a function could be made to format the order.

const order = {
"id": 111,
"name": "Matheus",
"phonenumber": "69993750103",
"reference": null,
"value_subtotal": "10.000",
"value_delivery": "5.000",
"value_total": "15.000",
"status": "pending",
"products": [
    {
        "name": "Açai 350ml",
        "OrdersProducts": {
            "quantity": 2,
            "price": "0.000"
        }
    },
    {
        "name": "acai 350ml",
        "OrdersProducts": {
            "quantity": 3,
            "price": "0.000"
        }
    }
  ]

};

 order.products = order.products.map(({OrdersProducts, ...other}) => ({...other, ...OrdersProducts})); 

I prefer custom toJSON methods. This, of course, depends on the access to the object structure.

Related