'How to reduce nested objects value in each model with Mongoose?
Let's say given following data:
[
{
_id: 61708f71ee435de97b5a82e7,
title: 'mjGPzpGLKIdea Title',
author: 61708f6dee435de97b5a82e2
votes: [
6171c8437234d56cfeff9986,
6171c8647234d56cfeff99de
]
},
{
_id: 6171c522069a2f6b396a430a,
title: 'MnJYCZFtyIdea Title',
author: 61708f7cee435de97b5a82f2,
votes: [ 6171c8927234d56cfeff9a45 ],
},
{
_id: 6171c523069a2f6b396a4315,
title: 'pcOKJzOEAIdea Title',
author: 61708f7cee435de97b5a82f2,
votes: [
6171c8327234d56cfeff9950,
6171c83c7234d56cfeff9967,
6171c85d7234d56cfeff99bb,
6171c8817234d56cfeff9a11
]
}
]
Each vote in votes has structure like this:
{
_id: 6171c8817234d56cfeff9a11, // some id
score: -1, // -1 or +1
}
How to get same array but with reduced score in each item using Mongoose:
[
{
_id: 61708f71ee435de97b5a82e7,
title: 'mjGPzpGLKIdea Title',
author: 61708f6dee435de97b5a82e2
scoreSum: 0 // -1 + 1
},
{
_id: 6171c522069a2f6b396a430a,
title: 'MnJYCZFtyIdea Title',
author: 61708f7cee435de97b5a82f2,
scoreSum: -1,
},
{
_id: 6171c523069a2f6b396a4315,
title: 'pcOKJzOEAIdea Title',
author: 61708f7cee435de97b5a82f2,
scoreSum: 3 // 1 + 1 + 1 - 1
}
]
I tried to use $reduce aggregation with $add, but $$this.score returns me null in the end. Like this:
MyModel.aggregate([
{
$addFields: {
scoreSum: {
$reduce: {
input: '$votes',
initialValue: 0,
in: { $add: ['$$value', '$$this.score'] },
},
},
},
},
])
I don't want to use javascript and I want to use only request to database and reduce value in elements. Thank you.
Solution 1:[1]
I dont know what are you doing wrong, but you need a lookup also.
Query
- lookup to join array with single field
(join happens ifvotesarray contains that_id) - reduce the and sume the scores
"$$REMOVE"is a system variable to remove the field votes, you can avoid it andprojectorunsetthe fieldvotes
authors.aggregate(
[{"$lookup":
{"from": "votes",
"localField": "votes",
"foreignField": "_id",
"as": "scoreSum"}},
{"$set":
{"scoreSum":
{"$reduce":
{"input": "$scoreSum",
"initialValue": 0,
"in": {"$add": ["$$value", "$$this.score"]}}},
"votes": "$$REMOVE"}}])
There is alternative solution with $lookup with pipeline, and instead of reduce, group by null and sum, but this looks more like your solution.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
