You are very close to a prettier solution :)
I do want to point out to OP that you had some syntax errors in your aggregation (missing $ in front of "events.early", some missing commas) so you may have been closer than you thought, but you're also forgetting to project the category field so you wouldn't be able to group on a field you don't project.
Here is the projection you want with slightly prettier syntax (more compact). Rather than using "" (empty string) I chose to use a date way in the past (I declared it as a variable) but it really doesn't matter what you use, of course, as long as you compare it to itself:
var never = new Date(0);
db.data.aggregate(
{ $project : {
category : 1,
early : {$cmp : [ {$ifNull : ["$events.early", never ] }, never ] },
late : {$cmp : [ {$ifNull : ["$events.late", never ] }, never ] }
} }
);
I'm taking advantage of the fact that the
$cmp comparison operator returns an integer - 0 when two strings are equal and 1 when the first value is greater than the second one (which is why I made my "never" a date type).
Asya