在MongoDB中,根据值对文档进行排序,并在第n个位置获取值

时间:2017-10-22 16:21:55

标签: mongodb mongoose

我在制定问题的标题方面遇到了麻烦,所以我的前提可能有些歪曲,但这就是这个想法。

我有一个看起来像这样的Mongoose架构,我对rating感兴趣:

var playerSchema = mongoose.Schema({
    playerName: {
        type: String,
        required: true,
        validate: dataFormatValidator.playerNameValidator,
        index: {
            unique: true,
            collation: {
                locale: 'en',
                strength: 2,
                caseLevel: false // 'AbC' == 'abc'
            }
        }
    },
    email: {
        type: String,
        validate: dataFormatValidator.emailValidator,
        index: {
            unique: true,
            sparse: true,
            collation: {
                locale: 'en',
                strength: 1,
                caseLevel: false
            }
        }
    },
    rating: {
        type: Number,
        default: 1200
    }
});

我想告诉玩家他们在整个玩家群中的位置,根据他们的等级,例如"你排在前31%和#34;。为了避免过多的数据库查询,我考虑每天一次通过数据库中的玩家,并将每个百分位的当前评级保存在一个看起来像这样的数组中,那么接近它的速度超快球员位置:

[1810, 1800, 1790 ... 420, 410]
  • 这是一个好方法吗?
  • 如何索引数据库并有效地查询这些数字?

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您的目标是:

  1. 在某个活动结束后更新播放器rating
  2. 以百分点的形式描述当前玩家对所有玩家的评分。
  3. 你实现这一目标的计划是:

    1. 在每场"游戏"。
    2. 之后记录rating
    3. 夜间,处理所有玩家rating,创建一个可用作查找表的阵列,以显示玩家彼此的相对位置。
    4. 对我而言,这个计划听起来似乎有道理。这假设您不需要实时显示百分比评分,而您的夜间任务可以处理您必须经历的玩家数量。如果你有数以百万计的玩家,这可能是一个挑战。

      您可以做的一个可能的改进是创建一个"预先汇总的报告"通过将数组存储在单独的文档/集合中,并更新此报告" (即阵列)在您更新播放器rating的同时。有关此技术的详细信息,请参阅https://docs.mongodb.com/ecosystem/use-cases/pre-aggregated-reports-mmapv1/

      使用预先汇总的报告的一个好处是,您不需要运行夜间任务(因此从长远来看可能更具可伸缩性),以及玩家的百分比数字可以实时显示(因为您每次在rating更新时都会更新数组)。此技术的一个缺点是,您需要为每次rating更新执行两次更新,而不是一次。

      注意:上面链接的预聚合报告用例包含MMAPv1存储引擎的详细信息,并且预先分配的部分不再与WiredTiger存储引擎相关。但是,基本思想可以应用于任一存储引擎。

答案 1 :(得分:0)

我通过定义每20分排名的“关键点”来解决这个问题,并节省了每个点数以上的玩家数量。我有一个看起来像这样的数组:

[
    { rating: 2000, playersAbove: 10 },
    { rating: 1980, playersAbove: 21 },
    ...
    { rating: 100, playersAbove: 128336 }
]

然后,每当玩家遇到其中一个限制时,我只需要更新数组中的一个值。例如,如果一个玩家从1990年到2001年的评级,我将数组中第一个对象的“playersAbove”增加一个。

要获得玩家的相对排名,我会检查有多少玩家比玩家上方和下方的“关键点”更好,并假设它们之间的曲线是线性的。然后我可以非常准确地估计有多少玩家比他更好。

enter image description here