【问题标题】:MongoDB sorting data failsMongoDB 排序数据失败
【发布时间】:2020-09-02 06:05:07
【问题描述】:

我试图在 mongo 中对大约 40k 个对象进行排序,我有两个集合,一个是漫画,另一个是角色,角色在里面有一个字段,其中包含一系列漫画 ID。我想要的是一个聚合框架的管道,它检索具有最强角色的漫画(每个角色的强度总和)。我能够获得包含每个角色力量总和的漫画列表,但是当我尝试对其进行排序时,数据库一直在等待,一切都以超时结束。我究竟做错了什么?

字符模型:

{
  _id: number,
  name: string,
  info: {
    alignment: string // can be "good" or "bad"
  }
  stats: {
    strength: number
  },
  comics: [] //array of numbers referencing the id of the comic
}

漫画模型:

{
  _id: number,
  name: string
}

这里是我的查询:

db.comics.aggregation(
            {
                $lookup: {
                    from: 'characters',
                    let: {
                        comic_id: '$_id',
                    },
                    as: 'total_comic_str',
                    pipeline: [
                        {
                            $match: {
                                $expr: {
                                    $and: [
                                        {$in: ['$$comic_id', '$comics']}, // the character is from this comic
                                        {$eq: ['$info.alignment', 'good']} // the character is a hero
                                    ]
                                }
                            }
                        },
                        {
                            $group: {  // group by comic id and accumulate strength of each hero
                                _id: '$$comic_id',
                                str: {
                                    $sum: '$stats.strength'
                                }
                            }
                        }
                    ]
                }
            },
            {
                $unwind: {
                    path: '$total_comic_str',
                    preserveNullAndEmptyArrays: false
                }
            },
            {
                $sort: {
                    'total_comic_str.str': -1
                }
            },
            {
                $limit: 1
            }
        )



【问题讨论】:

    标签: arrays mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您正面临光标超时。
    当您有查询游标(如 find() 返回的内容)时,您可以设置 noCursorTimeout()(这通常不是一个好的做法)以防止出现问题。
    但是当使用聚合时,Cursor 类型是不同的,所以没有noCursorTimeout

    作为一种解决方案,您可以使用$out 管道将聚合结果存储到临时集合中,然后根据需要使用生成的集合。

    【讨论】:

      【解决方案2】:

      $lookup 与管道有 shown to have performance issues 用于大型集合

      所以我建议只使用$lookup 而不使用管道。这将适用于您的特定数据集,该数据集具有相对较大的 characters 集合和可能较小的 comics 数组

      首先,最好在$lookup 中为您将要使用的内容编制索引,因此您应该为字段comics 添加索引,这样才能有有意义的改进。

      由于字符将是一个子文档数组,我们将使用$reduce而不是$group来计算总强度

      您的聚合管道应如下所示

      [
        {
          $lookup: {
            from: "characters",
            localField: "_id", // lookup with _id only we will filter out alignment later
            foreignField: "comics",
            as: "characters"
          }
        },
        {
          $project: {
            name: true,
            total_strength: {
              $reduce: {
                input: "$characters",
                initialValue: 0,
                in: {
                  $add: [
                    "$$value",
                    {
                      $cond: [
                        { $eq: [ "$$this.info.alignment", "good"] }, // calculating only "good" character here
                        "$$this.stats.strength",
                        0
                      ]
                    }
                  ]
                }
              }
            }
          }
        }, 
        {
          $sort: { total_strength: -1 }
        }, 
        {
          $limit: 1
        }
      ]
      

      【讨论】:

        猜你喜欢
        • 2015-04-04
        • 1970-01-01
        • 2012-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-11
        • 2011-05-27
        • 1970-01-01
        相关资源
        最近更新 更多