过去两天,我一直在寻找一个更好的解决方案,但没有提出任何建议。
基本上,我有一个包含如下文档的集合:
{ _id:5b5c92014fdd1f82c288530d
combine_id:1234
forty:4.65
broad:10.66
shuttle:4.18
threeCone:7.08
vert:40
bench:23
}
我希望能够在一个查询中获得每个字段的每个唯一值的总和。类似于:forty: [{time: 4.4, count: 7}, {time: 4.41, count: 11}, ...]
,但适用于文档中的所有六个字段。我想做的是为每个字段创建一个钟形曲线。
下面是我现在要查询的内容,但是我必须针对每个字段分别运行它,所以我认为必须有一个更好,更优雅的解决方案。
db.combine.aggregate([
{ $group: {
_id: {forty: '$forty'},
count: { $sum: 1 }
} } ]);
希望这是可能的,并且我已经提供了足够的信息。谢谢
答案 0 :(得分:1)
$facet
允许您在单个阶段内在同一组输入文档上创建多方面的聚合管道,因此您可以按以下方式获得每个字段的计数:
db.combine.aggregate([
{ '$facet': {
'forty': [{ '$group': { '_id': '$forty', 'count': { '$sum': 1 } } }],
'broad': [{ '$group': { '_id': '$broad', 'count': { '$sum': 1 } } }],
'shuttle': [{ '$group': { '_id': '$shuttle', 'count': { '$sum': 1 } } }],
'threeCone':[{ '$group': { '_id': '$threeCone', 'count': { '$sum': 1 } } }],
'vert': [{ '$group': { '_id': '$vert', 'count': { '$sum': 1 } } }],
'bench': [{ '$group': { '_id': '$bench', 'count': { '$sum': 1 } } }]
} }
])
要替换_id
键,您需要为每个构面附加一个 $project
流水线阶段,即
[
{ '$group': {
'_id': <facet_key>,
'count': { '$sum': 1 }
} },
{ '$project': {
'_id': 0,
'time': '$_id',
'count': 1
} }
]
稍作重构,如果六个字段是已知的并已修复,则可以动态创建管道,如下所示:
/* create the facet pipeline */
const getFacetPipeline = key => ([
{ '$group': {
'_id': '$'+key,
'count': { '$sum': 1 }
} },
{ '$project': {
'_id': 0,
'time': '$_id',
'count': 1
} }
]);
/* create the overall aggregate pipeline */
const getAggregationPipeline = keys => (
keys.reduce((acc, key) => {
acc['$facet'][key] = getFacetPipeline(key);
return acc;
}, { '$facet': {} })
);
/* get the pipeline for the six fields */
const pipeline = getAggregationPipeline([
'forty',
'broad',
'shuttle',
'threeCone',
'vert',
'bench'
]);
/* run the aggregate pipeline */
db.combine.aggretate([pipeline]);