Reputation: 8411
I have a document in an origin collection that holds OR not holds a reference to a foreign collection document - The key is not mandatory, so sometimes it's missing.
In such a situation the $lookup is "failed" and the desired document is not getting fetched from the DB.
This is the pipeline:
{
$lookup: {
from: "tables",
let: { "enginefuel_type": "$engine.fuel_type" },
pipeline: [
{ $match: { $expr: { $eq: ["$_id", "$$enginefuel_type"] }}},
{ $project: { title: 1 }}
],
as: "engine.fuel_type"
}
},
{
$unwind: "$engine.fuel_type"
},
{
$lookup: {
from: "tables",
let: { "enginegear": "$engine.gear" },
pipeline: [
{ $match: { $expr: { $eq: ["$_id", "$$enginegear"] }}},
{ $project: { title: 1 }}
],
as: "engine.gear"
}
},
{
$unwind: "$engine.gear"
}
I need the document to be found anyway - whether it has the engine.fuel_type and/or engine.gear fields or not. If there is, so it should take the document from the foreign, otherwise just remain empty but not ignore the whole document.
I thought about making some pre-if statement checking if the field exists before making the aggregate query (could also be more efficient, reducing requests to the DB).
Is there any good way to do that?
Upvotes: 0
Views: 925
Reputation: 96
Lookup stage works as you need it to, even though the field is not present in the origin collection, the document will not be ignored and will be a part of the result with "engine.fuel_type" array containing 0 elements.
It's the unwind stage that removes the documents which have 0 array elements. Fortunately, $unwind stage provides preserveNullAndEmptyArrays: option, that includes all the result. So you could try to do something like this:-
$lookup: {
from: "tables",
let: { "enginefuel_type": "$engine.fuel_type" },
pipeline: [
{ $match: { $expr: { $eq: ["$_id", "$$enginefuel_type"] }}},
{ $project: { title: 1 }}
],
as: "engine.fuel_type"
}
},
{
$unwind: {
path: "engine.fuel_type",
preserveNullAndEmptyArrays: true
}
}
Upvotes: 3