Reputation: 488
What I want to do is to query my database for documents and, if a field is not set, return a custom value instead of it.
Imagine I'm having a collection of songs
and some of these have the field pathToCover
set and some don't. For these, I want to return the URL to a placeholder image that I store in a config variable.
I am running node.js and mongoDB with express and mongoose.
I am not sure what the best approach for this is. An obvious solution would be to query for the documents and then in the callback iterate over them to check if the field is set. But this feels quite superfluous.
Currently, my code looks like this:
exports.getByAlbum = function listByAlbum(query, callback) {
Song.aggregate({
$group: {
_id: '$album',
artists: { $addToSet: '$artist' },
songs: { $push: '$title' },
covers: { $addToSet: '$pathToCover'},
genres: { $addToSet: '$genre'},
pathToCover: { $first: '$pathToCover'}
}
},
function (err, result) {
if (err) return handleError(err);
result.forEach(function(album) {
if ( album.pathToCover == null) {
album.pathToCover = config.library.placeholders.get('album');
}
})
callback(result);
});
}
What is the best approach for this?
Thanks a lot in advance!
Upvotes: 1
Views: 2503
Reputation: 151112
Where the value of the field is either null
or is unset and possibly missing from the document, then you use $ifNull
in your aggregation to set to the alternate value:
exports.getByAlbum = function listByAlbum(query, callback) {
var defaultCover = config.library.placeholders.get('album');
Song.aggregate(
[
{ "$group": {
"_id": "$album",
"artists": { "$addToSet": "$artist" },
"songs": { "$push": "$title" },
"covers": { "$addToSet": { "$ifNull": [ "$pathToCover", defaultCover ] } },
"genres": { "$addToSet": "$genre" },
"pathToCover": { "$first": { "$ifNull": [ "$pathToCover", defaultCover ] } }
}}
],
function (err, result) {
if (err) return handleError(err);
callback(result);
}
);
}
If it is an empty string then use the $cond
statement with an $eq
test in place of $ifNull
:
{ "$cond": [ { "$eq": [ "$pathToCover", "" ] }, defaultCover, "$pathToCover" ] }
Either statement can be used inside of a grouping operator to replace the value that is considered.
If you are just worried that perhaps not "all" of the values are set on the song, then use something like $min
or $max
as a appropriate to your data to just pick one of the values instead of using $first
.
Upvotes: 2