This is my product schema
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
create_at: {
type: Date,
default: Date.now,
required: true
},
quantity: {
type: Number,
required: true
},
brand: {
type: String,
default: '',
},
size: {
type: String,
},
images : {
type : [String],
},
color: [{
type: String,
}],
description: {
type: String,
},
details: {
type: String,
},
category: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'category'
},
status: {
type: Boolean,
default: true,
required: true
},
modified_at: {
type: Date,
default: Date.now
},
deleted_at: {
type: Date,
}
}, {
toJSON: { virtuals: true },
toObject: { virtuals: true }
});
This is my offer Schema
const mongoose = require('mongoose');
const offerSchema = new mongoose.Schema({
product: {
type:mongoose.Schema.Types.ObjectId,
ref: "Product",
},
category: {
type:mongoose.Schema.Types.ObjectId,
ref: "category",
},
offerType: {
type: String,
enum: [ "percentage", "price"],
},
offerValue: {
type: Number,
},
startDate: {
type: Date,
},
endDate: {
type: Date,
},
description: {
type: String,
},
createdAt: {
type: Date,
default: Date.now
}
});
const offerModel = new mongoose.model("Offers", offerSchema );
module.exports = offerModel;
I want to change the price of the product according to the offerModel
. If there is an offer for a product then the price should change according to the offer. But it is should not update in the database. I need it to be changed when I am retrieving it in the server side (all the time).
I use two ways to manipulate the data when querying it.
productSchema.virtual('discountPrice').get( async function() {
console.log('Inside the product schema virtual offer module');
const offer = await offerModel.find({});
console.log(offer);
return this.price - 100;
});
It works fine if I am not using the async. Virtual doesn't support the asynchronous functions.
But it is taking data from the database. So I can't write the code with out async or promise. The result is [object promise] not the product (when using async and promise).
Using pre('find')
It is not working as I expected. I don't know why.
productSchema.pre('find', async function() {
const offer = await offerModel.find();
console.log(offer);
if(offer){
this.price = this.price - 500;
console.log(this.price)
}else {
console.log('error in pre find in product schema')
}
});
I got the offer when querying but not changing the price in the product.
In short : how can I change the product price or add a new field discountPrice
. The price should be change based on if there is a offer for that particular product or category in the offerModel.js
Since you are storing a reference to product
in your offerSchema
you can populate
a virtual whenever you do a Product.find()
like so:
productSchema.virtual('offer', {
ref: 'Offer', //< You have named the model Offers
localField: '_id',
foreignField: 'product'
});
When you do your query just append populate
like so:
const products = await Product.find().populate('offer');
const product = await Product.findOne({name: 'Hat'}).populate('offer');
This will add an array consisting of one object to each Product
document. Therefore to calculate the discountPrice
of a product you just need to access the 0
indexed array element of offer
like so:
productSchema.virtual('discountPrice').get(function() {
// Implement logic to determine if offerType == percentage || price
return this.price - this.offer[0].offerValue;
});