That is a bit of a mouthful to say the least but I'll have another crack at explaining it:
You want:
For each "Position" value find the document whose "value" is less than the the largest "value" of the document with a "count" of less than four, whose own "count" is actually greater than 4.
Which reads like a math exam problem designed to confuse you with the logic. But catching that meaning then you perform the aggregation with the following steps:
db.positions.aggregate([
// Separate the values greater than and less than 4 by "Position"
{ "$group": {
"_id": "$Position",
"high": { "$push": {
"$cond": [
{ "$gt": ["$count", 4] },
{ "value": "$value", "count": "$count" },
null
]
}},
"low": { "$push": {
"$cond": [
{ "$lt": ["$count", 4] },
{ "value": "$value", "count": "$count" },
null
]
}}
}},
// Unwind the "low" counts array
{ "$unwind": "$low" },
// Find the "$max" value from the low counts
{ "$group": {
"_id": "$_id",
"high": { "$first": "$high" },
"low": { "$min": "$low.value" }
}},
// Unwind the "high" counts array
{ "$unwind": "$high" },
// Compare the value to the "low" value to see if it is less than
{ "$project": {
"high": 1,
"lower": { "$lt": [ "$high.value", "$low" ] }
}},
// Sorting, $max won't work over multiple values. Want the document.
{ "$sort": { "lower": -1, "high.value": -1 } },
// Group, get the highest order document which was on top
{ "$group": {
"_id": "$_id",
"value": { "$first": "$high.value" },
"count": { "$first": "$high.count" }
}}
])
So from the set of documents:
{ "Position" : 10, "value" : 1, "count" : 5 }
{ "Position" : 10, "value" : 3, "count" : 3 }
{ "Position" : 10, "value" : 4, "count" : 5 }
{ "Position" : 10, "value" : 7, "count" : 4 }
Only the first is returned in this case as it's value is less than the "count of three" document where it's own count is greater than 4.
{ "_id" : 10, "value" : 1, "count" : 5 }
Which I am sure is what you actually meant.
So the application of $min
and $max
really only applies when getting discrete values from documents out of a grouping range. If you are interested in more than one value from the document or indeed the whole document, then you are sorting and getting the $first
or $last
entries on the grouping boundary.
And aggregate is much faster than mapReduce as it uses native code without invoking a JavaScript interpreter.