首先,在发布此问题之前,我经历了几个类似的问题,但似乎没有一个满足我的需求,或者我无法以一种对我有用的方式来解释它们。
我正在MongoDB中(使用NodeJS和Mongoose)在MongoDB中进行聚合,以执行一些分页并提供诸如总计和平均值之类的数据。
到目前为止,这是我的管道:
[
{
$match: {
// Some filtering criteria here
}
},
{ $facet: {
metadata: [
{ $count: 'total' }
],
avg: [
{
$group: {
_id: null,
avg_price: {
$avg: "$price"
}
}
}
],
data: [
{ $sort: { createdDate: -1 }},
{ $skip: skip || 0 },
{ $limit: limit }
]
}
}
]
哪个给我的输出具有以下结构:
[
{
"metadata": [
{
"total": 14
}
],
"avg": [
{
"_id": null,
"avg_price": 936711.3571428572
}
],
"data": [
// the returned data according to $match, $sort, $skip and $limit
]
}
]
我必须将数据发送到前端,但是该结构不适合我的需求。我使用的是GraphQL,因此我希望发送类似以下的内容(没有这种array-object-array嵌套):
{
total: 14,
avg_price: 936711.3571428572,
data: [
// the returned data according to $match, $sort, $skip and $limit
]
}
我确实可以有一些Javascript逻辑来从聚合结果中提取数据并生成预期的输出,但是它需要像下面这样的脏代码:
avg_price: aggr_result[0].avg[0].avg_price
我想避免这种情况。
我想知道MongoDB在管道中进行这种格式化的方式是什么。
感谢您的时间。
答案 0 :(得分:2)
在管道的最后只使用一个$project
阶段
[
{ "$match": { ... }},
{ "$facet": {
"metadata": [
{ "$count": "total" }
],
"avg": [
{ "$group": {
"_id": null,
"avg_price": { "$avg": "$price" }
}}
],
"data": [
{ "$sort": { "createdDate": -1 }},
{ "$skip": skip || 0 },
{ "$limit": limit }
]
}
},
{ "$project": {
"total": { "$arrayElemAt": ["$metadata.total", 0] },
"avg_price": { "$arrayElemAt": ["$avg.avg_price", 0] },
"data": 1,
}}
]