I have the following document structure which contains an array of votes
:
{ _id: ObjectId("6350e2c1a15e0e656f4a7472"),
category: 'business',
votes:
[ { voteType: 'like',
userId: ObjectId("62314007da34df3f32f7cfc0") },
{ voteType: 'like',
userId: ObjectId("6356b5cbe2272ebf628451b") } ] }
What I would like to achieve is to add for each document the sum of votes for which voteType = like
, while keeping the original document, such as:
[ [{ _id: ObjectId("6350e2c1a15e0e656f4a7472"),
category: 'business',
votes:
[ { voteType: 'like',
userId: ObjectId("62314007da34df3f32f7cfc0") },
{ voteType: 'like',
userId: ObjectId("6356b5cbe2272ebf628451b") } ] }, {sum: 2, voteType: "like"} ], ...]
At the moment, the only workaround that I found is through an aggregation although I cannot manage to keep the original documents in the results:
db.getCollection('MyDocument') .aggregate([ {
$unwind: "$votes" }, {
$match: {
"votes.voteType": "like",
} }, {
$group: {
_id: {
name: "$_id",
type: "$votes.voteType"
},
count: {
$sum: 1
}
} },
{ $sort : { "count" : -1 } }, {$limit : 5}
])
which gives me:
{ _id: { name: ObjectId("635004f1b96e494947caaa5e"), type: 'like' },
count: 3 }
{ _id: { name: ObjectId("63500456b96e494947cbd448"), type: 'like' },
count: 3 }
{ _id: { name: ObjectId("63500353b6c7eb0a01df268e"), type: 'like' },
count: 2 }
{ _id: { name: ObjectId("634e315bb7d17339f8077c39"), type: 'like' },
count: 1 }
CodePudding user response:
You can do it like this:
$cond
with$isArray
- to check if thevotes
property is of the type array.$filter
- to filter votes based onvoteType
property.$size
- to get the sized of the filtered array.
db.collection.aggregate([
{
"$set": {
"count": {
"$cond": {
"if": {
"$isArray": "$votes"
},
"then": {
"$size": {
"$filter": {
"input": "$votes",
"cond": {
"$eq": [
"$$this.voteType",
"like"
]
}
}
}
},
"else": 0
}
}
}
}
])