0

How can I get the total price of specific item, I'm trying to multiply the quantity and the price and then POST it, but I'm having a hard time on how can I save the total amount of specific item

OrderSchema.js

const OrderSchema = new mongoose.Schema({
    userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
    products: [
        {
            productId:{
                type: mongoose.Schema.Types.ObjectId, ref: 'Product'
            },
            quantity: {
                type: Number,
                default: 1,
            },
            sellerId: {
                type: mongoose.Schema.Types.ObjectId, ref: 'User'            
            },
            totalPrice: {
                type: Number,
                default: 0,
            }

        }
    ],

}, {timestamps: true}
)

export default mongoose.model('Order', OrderSchema)

Order.js

const handleSubmit = async (e) =>{
    
    e.preventDefault()
    if(orderSummary?.location === ""){
       toast.error("Please input location..")
    }else{
        try {
            await userRequest.post(`/order`,{
                   userId: currentUser._id,
                   products: cart.products.map((item) =>({
                       productId: item._id,
                       quantity: item.quantity,
                       sellerId: item.seller_id._id,
                       totalPrice: Number(item.quantity * item._id.price)
                       
                   })),
               }) 

           } catch (error) {
               toast.error("Please put a Location and Time!")
           }
    }
    
}

in this image, I want to get the total amount of specific product, so the first product should have a 369. Image sample

But when I call my get all orders, this is what I get

 {
        "_id": "63b1b4de5a95bd4df7f9443b",
        "userId": {
            "_id": "63b18af8363f51fa50801dd0",
            "studentId": "1234567892"
        },
        "products": [
            {
                "productId": {
                    "_id": "63b16fc58fe585c7b81c748d",
                    "title": "asd",
                    "price": "123"
                },
                "quantity": 3,
                "sellerId": {
                    "_id": "63b160689f50f852e056afaf",
                    "studentId": "1234567890"
                },
                "_id": "63b1b4de5a95bd4df7f9443c"
            },
            {
                "productId": {
                    "_id": "63b16ff08fe585c7b81c7496",
                    "title": "asd21",
                    "price": "213"
                },
                "quantity": 3,
                "sellerId": {
                    "_id": "63b160689f50f852e056afaf",
                    "studentId": "1234567890"
                },
                "_id": "63b1b4de5a95bd4df7f9443d"
            }
        ],

    }

What I'm trying to get here when I call order.js

 {
        "_id": "63b1b4de5a95bd4df7f9443b",
        "userId": {
            "_id": "63b18af8363f51fa50801dd0",
            "studentId": "1234567892"
        },
        "products": [
            {
                "productId": {
                    "_id": "63b16fc58fe585c7b81c748d",
                    "title": "asd",
                    "price": "123"
                },
                "quantity": 3,
                "sellerId": {
                    "_id": "63b160689f50f852e056afaf",
                    "studentId": "1234567890"
                },
                "totalPrice": "369"
            },
            {
                "productId": {
                    "_id": "63b16ff08fe585c7b81c7496",
                    "title": "asd21",
                    "price": "213"
                },
                "quantity": 3,
                "sellerId": {
                    "_id": "63b160689f50f852e056afaf",
                    "studentId": "1234567890"
                },
                "totalPrice": "639"
            }
        ],

    }
Zurcemozz
  • 183
  • 1
  • 9
  • Have you tried [$sum](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sum/#-sum--aggregation-) – Joe Jan 02 '23 at 05:34
  • I am computing it in the front end, and throw it to the backend. Do you think it's applicable to create a cart reducer wherein it will compute the actual state? – Zurcemozz Jan 02 '23 at 09:17
  • but I'll try this @Joe! Thanks for recommendation – Zurcemozz Jan 02 '23 at 10:08

1 Answers1

0

You can use a virtual field to calculate the totalPrice value:

const OrderSchema = new mongoose.Schema(
  {
    userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
    products: [
      {
        productId: {
          type: mongoose.Schema.Types.ObjectId,
          ref: "Product",
        },
        quantity: {
          type: Number,
          default: 1,
        },
        sellerId: {
          type: mongoose.Schema.Types.ObjectId,
          ref: "User",
        },
        // NOTE: Remove this
        // totalPrice: {
        //   type: Number,
        //   default: 0,
        // },
      },
    ],
  },
  {
    timestamps: true,

    // NOTE: Add this or it may not work
    toJSON: { virtuals: true },
    toObject: { virtuals: true },
  }
);

OrderSchema.virtual("totalPrice").get(function () {
  if (!this.productId) return undefined; // Guard clause in case it is not populated
  return this.productId * this.quantity;
});

export default mongoose.model("Order", OrderSchema);

This acts almost exactly like a normal field, however, it is not actually a part of the document. So if you were to query for the least totalPrice, it would act as if the field does not exist.

Pros:

  • Very performant, since it does not query data
  • Does not require any complex/hard to read code for such a simple task

Cons:

  • Requires the productId field to be populated
  • Cannot be searched in a query

Given that in most cases, you WILL need the productId field populated, this is a better suited solution. Let me know if there are any errors, since I can't really test this without making a whole project.

Tidris
  • 114
  • 2
  • 8