【问题标题】:Aggregate function on mongo running very slow when running query运行查询时,mongo上的聚合函数运行速度非常慢
【发布时间】:2019-12-16 08:07:01
【问题描述】:

尝试在 Mongo 上运行聚合函数的查询,当我希望的结果不到一秒时,该查询当前需要 16 秒

{
  "$lookup": {
    "from": "session_attendances",
    "let": { "id": "$_id" },
    "pipeline": [
      {
        "$match": {
          "$expr": {
            "$eq": ["$student", "$$id"]
          }
        }
      },
      {
        "$project": {
          "attendance_code": "$attendance_code"
        }
      }
    ],
    "as": "attendance"
  }
},
{
  // keep only matched students, can skip this and modifiy the next phase incase no such documents exists.
  "$unwind": "$attendance"
},
{
  "$lookup": {
    "from": "attendance_codes",
    "let": { "attendance_code": "$attendance.attendance_code" },
    "pipeline": [
      {
        "$project": {
          "type": 1
        }
      },
      {
        "$match": {
          "$expr": {
            "$eq": ["$_id", "$$attendance_code"]
          }
        }
      }
    ],
    "as": "attendance_code"
  }
},
{
  //again assuming we want to keep matched docs otherwise why lookup?
  "$unwind": "$attendance_code"
},
{
  "$group": {
    "_id": { "a": "$attendance.attendance_code", "id": "$_id" },
    "total": { "$sum": 1 },
    "data": { "$first": "$$ROOT" } // if u want to keep document data
  }
}

希望有人可以回答我的代码的哪一部分导致运行时间如此缓慢。

【问题讨论】:

标签: mongodb aggregate-functions


【解决方案1】:

不清楚你的最终目标是什么,如果你想澄清它会帮助我为你当前的聚合提供一个替代方案

话虽如此,第二个查找阶段是“无用的”,因为您在不使用它获得的任何数据的情况下立即进行分组,删除它仍然可以获得完全相同的结果并节省一些时间。

假设由于某种原因需要第二次查找,我建议不要嵌套它,而是在第一次查找之后使用,如下所示:

{
        $lookup: {
            from: 'session_attendances',
            let: { 'id': '$_id' },
            pipeline: [
                {
                    "$match": {
                        "$expr": {
                            "$eq": ["$student", "$$id"]
                        }
                    }
                }
                ,{
                    $project: {
                        attendance_code: '$attendance_code'
                    }
                }
            ],
            as: 'attendance'
        }
    },
    {// keep only matched students, can skip this and modifiy the next phase incase no such documents exists.
       $unwind: "$attendance" 
    },
    {
       $lookup: {
           from: 'attendance_codes',
           let: { 'attendance_code': '$attendance.attendance_code' },
            pipeline: [
               {
                 $project: {
                    type: 1
                 }
               },
               {
                 "$match": {
                     "$expr": {
                         "$eq": ["$_id", "$$attendance_code"]
                   }
               }],
               as: 'attendance_code'
                    }
         }
   },
   { //again assuming we want to keep matched docs otherwise why lookup?
     $unwind: "$attendance_code"
   },
   {
        $group: {
            _id: {a: "$attendance.attendance_code", id: "$_id"}
            total: { $sum: 1 },
            data: {$first: "$$ROOT"} // if u want to keep document data
       } 
   }

这应该会给你更好的性能,我也建议放弃项目阶段,除非文档非常大,否则这通常不会帮助性能反而会损害它。

【讨论】:

猜你喜欢
  • 2016-02-10
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多