Вы можете использовать этап $ facet , чтобы собрать значения года и удалить ненужные поля, затем $ unwind оба из них и, наконец, использовать $ group чтобы сопоставить значения.
Быстрый и грязный пример:
db.aggtest.aggregate([
{$facet:{
years:[
{$group:{ _id:null,
listC:{$addToSet: "$timeDoneC.year"},
listB:{$addToSet:"$timeDoneB.year"},
listA:{$addToSet:"$timeDoneA.year"}}},
{$project:{ _id:0,
list:{$setUnion:["$listA","$listB","$listC"]}}}],
done:[{$project:{ _id:0,
timeDoneA:"$timeDoneA.year",
timeDoneB:"$timeDoneB.year",
timeDoneC:"$timeDoneC.year"}}]}},
{$unwind:"$done"},
{$unwind:"$years"},
{$unwind:"$years.list"},
{$group:{ _id:"$years.list",
timeDoneA:{$sum:{$cond:[{$eq:["$done.timeDoneA","$years.list"]},1,0]}},
timeDoneB:{$sum:{$cond:[{$eq:["$done.timeDoneB","$years.list"]},1,0]}},
timeDoneC:{$sum:{$cond:[{$eq:["$done.timeDoneC","$years.list"]},1,0]}}}}])
Проверка этого на ваших образцах данных дает:
{ "_id" : 2020, "timeDoneA" : 2, "timeDoneB" : 1, "timeDoneC" : 1 }
{ "_id" : 2019, "timeDoneA" : 0, "timeDoneB" : 1, "timeDoneC" : 1 }