Reputation: 2580
I have a list of objects where each object has a count
value. Is it possible to update a total
field without $sum
ing all the values after one of the values has changed?
For example, given the following data
{
"elements": [
{"id": "A", "count": 1},
{"id": "B", "count": 2},
{"id": "C", "count": 3},
],
"total": 6
}
I want to update object A's count
to 2
and total
to 7
Upvotes: 1
Views: 437
Reputation: 36144
There is no straight way to handle this situation, you can use update with aggregation pipeline starting from MongoDB 4.2,
$map
to iterate loop of elements
and update count
when condition id
match$sum
of countdb.collection.update({
"elements.id": "B"
},
[
{
$set: {
elements: {
$map: {
input: "$elements",
in: {
id: "$$this.id",
count: {
$cond: [
{ $eq: ["$$this.id", "A"] },
2,
"$$this.count"
]
}
}
}
}
}
},
{ $set: { total: { $sum: "$elements.count" } } }
])
Upvotes: 1
Reputation: 354
First of all, I would stronget suggest you to use Mongoose in your project, as it will provide pretty powerfull tools to access the information contained in your MongoDB. For example, the easiest to get a dynamically updated total would be turning this field into a virtual one:
YourSchema.virtual("total").get(function () {
this.elements.map(element => element.count).reduce((accumulator, currentValue) => accumulator + currentValue);
});
If you need the field not to be virtual, I would suggest using Mongoose's middleware YourSchema.pre("save") to update the total field each time an entry from this collection is modified.
YourSchema.pre("save", function (next) {
this.total = this.elements.map(element => element.count).reduce((accumulator, currentValue) => accumulator + currentValue);
next();
});
Upvotes: 1