MongoDB do not return document if condition in lookup fails

Solution 1:

Once you perform the $lookup you can filter out the documents with an empty array:

{ $match: { album: { $ne: [] } }}

Then there is an example in the MongoDB documentation for the $mergeObjects operator that is very similar to your case. Assuming that each song belongs to one album, put together your aggregation pipeline may look like this:

db.songs.aggregate([
{
    $lookup: {
            from: "albums",
            let: { album: '$album' },
            as: "album",
            pipeline: [{
                $match: {
                    $expr: {
                        $and: [
                            { $eq: ['$albumId', '$$album._id'] },
                            { $eq: ['$status', 'Draft'] },
                        ]
                    }
                }
            }]
        }
},
{   $match: { album: { $ne: [] } }},
{
    $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$album", 0 ] }, "$$ROOT" ] } }
},
{ $project: { album: 0 } }
])

Solution 2:

You may want to experiment going in the other direction: find albums in status = Draft then get the songs:

db.album.aggregate([
    {$match: {"status":"Draft"}}
    ,{$lookup: {from: "song",
        localField: "album", foreignField: "album",
                as: "songs"}}
    // songs is now an array of docs.  Run $map to turn that into an
    // array of just the song title, and overwrite it (think  x = x + 1):
    ,{$addFields: {songs: {$map: {
                            input: "$songs",
                            in: "$$this.song"
    }} }}
]);

If you have a LOT of material in the song document, you can use the fancier $lookup to cut down the size of the docs in the lookup array -- but you still need the $map to turn it into an array of strings.

db.album.aggregate([
    {$match: {"status":"Draft"}}
    ,{$lookup: {from: "song",
                let: { aid: "$album" },
                pipeline: [
                    {$match: {$expr: {$eq:["$album","$$aid"]}}},
                    {$project: {song:true}}
                ],
                as: "songs"}}

    ,{$addFields: {songs: {$map: {
                            input: "$songs",
                            in: "$$this.song"
    }} }}

]);