管道的性能问题,对动态$项目进行排序

时间:2017-11-02 10:48:54

标签: mongodb performance sorting projection ranking

我在这个给定的聚合上遇到了性能问题:

db.users.aggregate([
  { 
    // reduce to users that have first or second level users in their friends list
    "$match:": {"friendOf": {"$in": [ObjectId("59b1b8025c69f2ae693f36d7"), ObjectId("59b1b8025c69f2ae693f36d8"), ObjectId("59b309835c69f24829057eb5"), ObjectId("59b458aa5c69f272513907e5")}}
  },
  {
    "$addFields": {
      "ranking": {
        "$sum": [
          {
            "$cond": {
              "if": { // first level friends
                "$setIsSubset": ["$friendOf", [ObjectId("59b1b8025c69f2ae693f36d7"), ObjectId("59b1b8025c69f2ae693f36d8")]]
              },
              "then": 2, // weight: 2
              "else": 0
            }
          },
          { 
            "$cond": {
              "if": { // second level friends
                "$setIsSubset": ["$friendOf": [ObjectId("59b309835c69f24829057eb5"), ObjectId("59b458aa5c69f272513907e5")]]
              },
              "then": 1, // weight: 1
              "else": 0
            }
          }
        ]
      }
    }
  },
  {
    "$sort": {"ranking": 1}
  },
  {
    "$limit": 20
  }
]);

使用用户集合,其中'friendOf'属性获取对应的ObjectId()列表,如果用户有其他用户为朋友。

查询的目标是按用户与第一个用户列表的接近程度对用户进行排序。

我遇到的问题是我使用“排名”键作为排序字段。

由于它是一个依赖于查询的投影,我无法预先计算并存储此字段以使Mongo索引受益。

由于查询的目的是排名,我不能在$ sort之前“限制”范围。

所以,我正在寻找一种更好的方法来解决我的问题。

注意:我使用的是MongoDB 3.4.10版本

此致

1 个答案:

答案 0 :(得分:0)

实际上你只有2级朋友吗? 1点和2点?你会想看到21-40的结果吗?如果没有,那么您可以简单地对MongoDB进行两次查询,并在_id$sum:1上使用$ group来获取朋友总数,在AF内执行$ sort和$ limit 20步骤然后合并你的应用程序中的2和度假,以应用2分评分。