I have a collection filled with documents looking somehting like this:
{ _id: <id> arrayOne: [{name: <string>, listings: [<string>, <string>, ...]}], arrayTwo: [{name: <string>, listings: [<string>, <string>, ...]}] } What i need is a flat array where each string in listings from both arrayOne and arrayTwo is represented without duplicates, so I do this:
aggregate( [ { $match: { _id: <id>} }, { $unwind: '$arrayOne' }, { $unwind: '$arrayOne.listings' }, { $unwind: '$arrayTwo' }, { $unwind: '$arrayTwo.listings' }, { $group : { _id : '$_id', setOne: { $addToSet: '$arrayOne.listings'}, setTwo: {$addToSet: '$arrayTwo.listings'} } }, { $project: {unique_appearances: {$setUnion: ['$setOne', '$setTwo']}}} ] ); This works just fine until we run this on a document where arrayOne or arrayTwo is empty.
Today, I solve it by adding a fake value (before unwinding), which i filter out at the last line, like this:
aggregate( [ { $match: { _id: <id>} }, { $project: { _id: '$_id', arrayOne: { $cond : [{$gt: ['$arrayOne', []]}, '$arrayOne', [{listings: ['cheezeburglars']}]] }, arrayTwo: { $cond: [{$gt: ['$arrayTwo', []]}, '$arrayTwo', [{listings: ['cheezeburglars']}]] } } }, { $unwind: '$arrayOne' }, { $unwind: '$arrayOne.listings' }, { $unwind: '$arrayTwo' }, { $unwind: '$arrayTwo.listings' }, { $group : { _id : '$_id', setOne: { $addToSet: '$arrayOne.listings'}, setTwo: {$addToSet: '$arrayTwo.listings'} } }, { $project: { unique_appearances: { $setDifference: [{$setUnion: ['$setOne: ', '$setTwo']}, ['cheezeburglars']] } }} ] ); This works, but I feel that my solution is a bit hacky. Is there a better way to solve this?