2016-08-13 316 views
2

我有一个文档集合,我希望按字段进行分组,除非它不存在,那么我想按第二个字段进行分组。

例如,考虑这4个文件:

{ 
    prop1: 'anything', 
    prop2: 1 
}, 
{ 
    prop1: 'anything', 
    prop2: 2 
}, 
{ 
    prop1: 'something' 
}, 
{ 
    prop1: 'something else' 
} 

当我按 'PROP2' 我会得到3个分组结果。一为:

PROP2 == 1和

PROP2 == 2和

PROP2 ==未定义

但我希望得到4个结果。一为:

PROP2 == 1和

PROP2 == 2和

PROP1 == '东西' 和

PROP1 == '别的东西'

这甚至可能吗?这是一个非常复杂的查询吗?我最好填补缺失的领域,以便它可以分组?

回答

2

您需要在$group阶段使用$ifNull条件聚合操作符。

db.coll.aggregate([ 
    { "$group": { "_id": { "$ifNull": [ "$prop1", "$prop2" ] } } } 
]) 

$ifNull的操作者返回第二个表达式的值,如果第一表达式的计算结果为空值,或者如果该字段是丢失。这就是你想要的。


您可能需要一个$project阶段添加到您的管道,但是这是将是多余的,造成的性能在应用程序的下降。

+0

这正是我所期待的。谢谢。 – smdufb

2

可以在$project阶段使用$ifNull运营商分组之前如下

db.cullection.aggregate(
    { $project: { "groupVal": { $ifNull: [ '$prop2', '$prop1' ] } } }, 
    { $group: { "_id": "$groupVal" } } 
); 

对于每一个文档,将根据其应在下一阶段$group进行分组设定的值groupVal。因此,对于定义了prop2字段的文档,将从prop2中选择值,否则将从prop1中获取值。

+0

这可能是由于我对mongodb及其查询缺乏了解。但是在$ project阶段执行此操作会以某种方式在结果中将累积器设置为小组阶段(例如'prop1:{$ first:'$ prop1'}')为'null'。 – smdufb

+0

是的,只有一个“$ group”阶段的解决方案肯定更好!我没有注意到'$ ifNull'操作符可以用在'$ group'阶段以及'$ project'阶段。您可以在'$ project'阶段使用[**'$$ ROOT' **](https://docs.mongodb.com/manual/reference/aggregation-variables/#variable.ROOT)运算符来传递整个文档没有'null'值到'$ group'阶段。 – tarashypka