I have a collection of items that can be upvoted or downvoted.
{"_id" : 1, "name": "foo", "upvotes" : 30, "downvotes" : 10} {"_id" : 2, "name": "bar", "upvotes" : 20, "downvotes" : 0} {"_id" : 3, "name": "baz", "upvotes" : 0, "downvotes" : 0}
I'd like to use aggregation to calculate the quality
db.items.aggregate([ {"$project": { "name": "$name", "upvotes": "$upvotes" "downvotes": "$downvotes", "quality": {"$divide":["$upvotes", "$downvotes"]} } }, {"$sort": {"quality":-1}} ]);
Obviously this doesn't work, because of division by zero. I need to implement appropriate conditioning:
if upvotes != 0 and downvotes == 0 then the quality = upvotes if upvotes and downvotes are both 0 then the quality is 0
I tried tweaking downvotes by 1 using ternary idiom. But to no avail.
db.items.aggregate([ {"$project": { "name": "$name", "upvotes": "$upvotes", "downvotes": "$downvotes" ? "$downvotes": 1 } }, {"$project": { "name": "$name", "upvotes": "$upvotes" "downvotes": "$downvotes", "quality": {"$divide":["$upvotes", "$downvotes"]} } }, {"$sort": {"quality":-1}} ]);
How can I integrate this kind of conditioning within mongodb aggregation framework?
In MongoDB, the $divide aggregation pipeline operator divides one number by another and returns the result. To use $divide , pass the numbers in an array. The $divide operator will divide the first number by the second number. In other words, the first number is the dividend, and the second number is the divisor.
You can use $and with aggregation but you don't have to write it, and is implicit using different filters, in fact you can pipe those filters in case one of them needs a different solution.
The aggregate() Method For the aggregation in MongoDB, you should use aggregate() method.
To sort the whole array by value, or to sort by array elements that are not documents, identify the input array and specify 1 for an ascending sort or -1 for descending sort in the sortBy parameter.
You might want to use the $cond operator to handle this:
db.items.aggregate([ {"$project": { "name": "$name", "upvotes": "$upvotes", "downvotes": "$downvotes", "quality": { $cond: [ { $eq: [ "$downvotes", 0 ] }, "N/A", {"$divide":["$upvotes", "$downvotes"]} ] } } }, {"$sort": {"quality":-1}} ]);
You want the $cond operator. http://docs.mongodb.org/manual/reference/operator/aggregation/cond/
Something like:
{"$project": { "name": "$name", "upvotes": "$upvotes", "downvotes": { $cond: [ { $eq: ["$downvotes", 0] }, 1, "$downvotes"] } } },
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With