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?