非规范化字段的性能与单独集合的使用

时间:2014-09-08 02:27:11

标签: mongodb meteor

我正在考虑跟踪每位用户的得分/分数。从我看过的例子来看,跟踪一个字段中某些事物的总数似乎是正常的。但是,我担心能够在作弊的情况下回溯或跟踪给予用户的分数/分数。这就是我的想法:

Meteor.User Collection:

Meteor.user.profile: {
    ...
    totalScore: 0
    ...
}

场景1: 只需添加总分并按用户跟踪:

updateScore() {
       var currentUser = Meteor.user();

       currentUser.profile.update({ _id: this._id }{$inc: { totalScore: 1} });
}

场景1: 在添加到用户总分之前,先将分数放入单独的Collection中进行记录:

分数收集:

Scores: {
    playerId: ,
    score: ,
    ...
}


updateScore() {
       var currentUser = Meteor.user();
       Scores.insert({ playerId: this._id, score: 1, ...});
       currentUser.profile.update({ _id: this._id }{$inc: { totalScore: 1} });

       //if not the above, then thisor this

       var currentUserScore = Calculate total score count from Scores collection of current user here
       Meteor.user.profile.update({ _id: this._id }{$set: { totalScore: currentUserScore} });

}

所以我想知道的是,场景2对场景1有意义吗?如果场景2有意义,如果我通过变量currentUserScore计算总得分,那么使用它来更新用户的totalScore个人资料字段(每次需要更新得分时都会运行),这会对应用程序的性能产生不利影响吗?

1 个答案:

答案 0 :(得分:1)

根据我们的讨论,场景2对我来说最有意义,特别是考虑到得分历史可能在审计总数之外具有价值。请记住,删除数据总是比创建数据更容易,所以即使历史记录没有用处,也可以在以后删除集合时没有任何害处。

我会实现这样的addScore方法:

Meteor.methods({
  addScore: function(score) {
    check(score, Number);

    Meteor.users.update(this.userId, {
      $inc: {'profile.totalScore': score}
    });

    Scores.insert({
      playerId: this.userId,
      score: score,
      createdAt: new Date()
    });
  }
});

除非你能想到这样做的令人信服的理由,否则我怀疑每次聚合totalScore的db /计算开销是不值得的。这样做只能修复用户通过直接更新她的个人资料而被欺骗的情况。您可以通过添加以下内容来解决此问题:

Meteor.users.deny({
  update: function() {
    return true;
  }
});

我建议添加上述内容,无论您使用哪种解决方案,因为即使insecure已被删除,用户个人资料也可以由用户直接更新。有关详细信息,请参阅文档的this section

最后,如果您要审核每个用户的totalScore,您可以将总计作为nightly process的一部分进行汇总,而不是每次添加新分数时。您可以通过提取Scores文档在服务器上执行此操作,也可以直接在mongodb中使用aggregation执行此操作。注意后者会要求你使用流星之外的一个过程(我的理解是流星的聚合包目前不起作用,但你可能想自己研究一下)。