Let's say I have a document like this
{
"_id" : "PQ8GUYYB7IERPNE9NX-CombQQD7F",
"combId" : 5,
"alignToOffer" : true,
"product" : "TwBuYJZquKeKTmtwr",
"price" : 85,
}
now i want to get average of each combination of same product to align (if it's checked to align) so am using the meteor observe handle to do this. and get aggregated average price values it on every changes for related documents
Offers.find({}).observe({
changed: function(offer, fields) {
var result = Offers.aggregate(
[
{
$match:
{
product: offer.product,
status: true,
combId: Number(offer.combId)
}
},
{
$group:
{
_id: "$product",
priceAlign: { $avg: "$price" },
minPrice: { $min: "$price" }
}
}
]
);
if ( result.length ){
var averageValue = parseFloat(Math.round(result[0].priceAlign * 100) / 100).toFixed(2),
bestOffer = parseFloat(Math.round(result[0].minPrice * 100) / 100).toFixed(2);
var updateValues = { $set: {
avgOffer: averageValue,
bestOffer: bestOffer
}};
var updatePrice = { $set: {
price : averageValue
}};
Offers.update({
product: offer.product,
combId: offer.combId,
status: true
}, updateValues, {multi: true});
Offers.update({
product: offer.product,
combId: offer.combId,
alignToOffer: true,
status: true
}, updatePrice, {multi: true});
}
}
});
it's works perfectly, there is the REAL Issue to save average price. to conclude i have three documents for same product, two of them aligned (align to offer key checked) and one is not, now when I changed the fixed value doc price(which is not aligned) then the other two will save with +1
or -1
(with decimal places) not the same price ie if i save the fixed price with 96
the other one will have the price of 95.99999999999996
or 96.00000000000001
not 96
. I need here a whole number but when i remove decimal values with any method of vanilla JS. eg toFixed()
it will give me 1 less or 1 more value. I bumping my head on PC since night. Any help will be greatly appreciated.
last change yet give me 96.01
or 95.99
You don't need to put extra logic for calculatin avg.
just follow below step OR use mongoDB $avg
operator.
1) In your case first you get all document that have alignToOffer: false
.
2) After calculating it's average using aggregation
. OR manually calculate like below.
3) Set in those document that alignToOffer: true
simple.
1)
let result = Offers.find({ product: offer.product, status: true, alignToOffer: false, combId: Number(offer.combId) }).fetch(); //fetch for meteor.
2)
// if get only one document then set it's price no need to calculate avg let avg = result.length > 1 ? result.map(obj => obj.price).reduce((o,n) => o + n) / result.length : result[0].price;
3)
Offers.update({ product: offer.product, alignToOffer: true, status: true, combId: Number(offer.combId) }, {$set:{ price : Number(avg) }}, { multi: true });
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.