【问题标题】:Formatting data after $facet aggregation in mongodb在 mongodb 中 $facet 聚合后格式化数据
【发布时间】:2019-06-05 14:34:39
【问题描述】:

首先,在发布此问题之前,我已经经历了几个类似的问题,但似乎没有一个问题能准确地满足我的需求,或者我无法以适合我的方式解释它们。

我正在使用 MongoDB 中的聚合(使用 NodeJS 和 Mongoose)来执行一些分页,并提供一些数据,例如总数和平均值。

这是我目前的管道:

[
    { 
      $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,我希望发送如下内容(没有那种数组对象数组的嵌套):

 {
    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 在管道中处理这种格式的方法是什么。

感谢您的宝贵时间。

【问题讨论】:

    标签: node.js mongodb mongodb-query aggregation-framework


    【解决方案1】:

    只需在管道末端使用一个$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,
      }}
    ]
    

    【讨论】:

    • 像魅力一样工作。谢谢!我没有关于 $arrayElemAt 的先验知识,所以也谢谢你。
    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 2018-02-01
    • 2017-07-19
    相关资源
    最近更新 更多