Se carros e bicicletas não tiverem IDs comuns, você poderá pesquisar sequencialmente em matrizes separadas e combiná-los com $setUnion :
db.vehicles.aggregate([
{$lookup: {
from: "cars",
localField: "vehicleId",
foreignField: "_id",
as: "carDetails"
}},
{$lookup: {
from: "bikes",
localField: "vehicleId",
foreignField: "_id",
as: "bikeDetails"
}},
{$project: {
vehicleType: 1,
vehicleId: 1,
vehicleDetails:{$setUnion: [ "$carDetails", "$bikeDetails" ]}
}},
{$project: {
carDetails:0,
bikeDetails:0,
}}
]);
Caso contrário, você precisará usar $facet para filtrar veículos por tipo antes da pesquisa:
db.vehicles.aggregate([
{
$facet: {
"cars": [
{$match: {"vehicleType": "cars"}},
{$lookup: {
from: "cars",
localField: "vehicleId",
foreignField: "_id",
as: "vehicleDetails"
}},
],
"bikes": [
{$match: {"vehicleType": "bikes"}},
{$lookup: {
from: "bikes",
localField: "vehicleId",
foreignField: "_id",
as: "vehicleDetails"
}}
]
}
},
{$project: {all: {$setUnion: ["$cars", "$bikes"]}}},
{$unwind: "$all"},
{$replaceRoot: { newRoot: "$all" }}
])