我有一个装满文件的集合,看起来像这样:
{
_id: <id>
arrayOne: [{name: <string>, listings: [<string>, <string>, ...]}],
arrayTwo: [{name: <string>, listings: [<string>, <string>, ...]}]
}
我需要的是一个平面数组,其中来自arrayOne和arrayTwo的列表中的每个字符串都没有重复,所以我这样做:
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']}}}
] );
这可以正常工作,直到我们在arrayOne或arrayTwo为空的文档上运行它。
今天,我通过添加一个伪值(在展开之前)解决它,我在最后一行过滤掉了,如下所示:
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']]
}
}}
] );
这很有效,但我觉得我的解决方案有点笨拙。有没有更好的方法来解决这个问题?
答案 0 :(得分:3)
您可以在MongoDB 3.2+中执行此操作,方法是在相关$unwind
阶段添加preserveNullAndEmptyArrays: true
选项:
aggregate( [
{ $match: { _id: <id>} },
{ $unwind: { path: '$arrayOne', preserveNullAndEmptyArrays: true } },
{ $unwind: '$arrayOne.listings' },
{ $unwind: { path: '$arrayTwo', preserveNullAndEmptyArrays: true } },
{ $unwind: '$arrayTwo.listings' },
{ $group : { _id : '$_id', setOne: { $addToSet: '$arrayOne.listings'}, setTwo: {$addToSet: '$arrayTwo.listings'} } },
{ $project: {unique_appearances: {$setUnion: ['$setOne', '$setTwo']}}}
] );
设置该选项将导致$unwind
仍然在输出中包含文档,即使该字段为空(或为空或缺失)。