我正在聚合管道中执行$group
,其中我将$push
的一个属性添加到数组,而对于所有其余属性,我只需要使用$first
:
{ $group: {
'_id': '$_id',
property1: { $push: '$property1' },
property2: { $first: '$property2' },
property3: { $first: '$property3' },
property4: { $first: '$property4' },
property5: { $first: '$property5' },
property6: { $first: '$property6' },
property7: { $first: '$property7' },
// …
}},
是否有可能以更简洁的方式进行指定?我希望以下内容(不起作用)表示“ $push
使用property1
,其他任何内容使用$first
”
{ $group: {
'_id': '$_id',
property1: { $push: '$property1' },
'*': { $first: '$*' }
}},
答案 0 :(得分:1)
不,没有其他办法。您必须在$first
阶段使用$group
累加器指定每个字段。
但是您可以避免为每个字段指定$first
。像这样
{ "$group": {
"_id": "$_id",
"property1": { "$push": "$property1" },
"data": {
"$first": {
"property2": "$property2",
"property3": "$property3",
"property4": "$property4",
"property5": "$property5",
"property6": "$property6",
"property7": "$property7"
}
}
}}
答案 1 :(得分:1)
如上所述,安东尼·温兹莱特(Anthony Winzlet)无法通过$group
运算符来实现这一目标。但是,我使用了以下解决方法,这使我不必显式列出所有这些属性。拥有少量属性可能不值得麻烦,如果您不需要照顾灵活性,可以稍后再添加其他属性,但就我而言,这是有道理的。
这里是聚合管道的想法:
$addFields
将整个根文档添加为临时副本。$push
,对于以前复制的整个子文档,请使用$first
运算符。$replaceRoot
和$mergeObjects
来获取复制的根文档,并将属性替换为$push
聚合。这是一个例子:
db.getCollection('test').aggregate([
{ $addFields: { tempRoot: '$$ROOT' } },
{ $group: { '_id': '$property1', 'property2': { $push: '$property2' }, 'tempRoot': { $first: '$tempRoot' } } },
{ $replaceRoot: { newRoot: { $mergeObjects: [ '$tempRoot', { property2: '$property2' } ] } } }
]);