使用RESTful API在MongoDB应用程序中对“关注者计数”进行数据建模

时间:2013-05-14 19:59:26

标签: api mongodb rest

我有一个User实体,其中包含他/她正在关注的其他用户ID数组。

var userSchema = {
  following: { type: Array }
};

我有一个RESTful API,当我请求User时,我的应用程序需要知道User有多少关注者。

我看到的两个选项是:

  • 请求User时,请执行计数查询,例如:{ following: { $in: [userId] } }
  • UserPOST编辑时,请检查是否已向following数组添加或删除了任何用户ID,如果是,请使用MongoDB的$inc增加或减少已跟踪/取消关注的followersCount文档上的User属性。

他们还有其他选择吗?如果没有,最好的选择是什么?我觉得在文档本身中放置一个followersCount属性有点奇怪,因为这表明它可以由应用程序更新,而实际上它只是一个动态计数。

我有类似的情况,我需要我的RESTful API来返回与article相关联的website的数量。我是根据要求计算该网站的文章,还是每次创建与该网站相关的新文章时都存储计数属性并更新它?

2 个答案:

答案 0 :(得分:0)

你想要的方式是正确的方式。 MongoDB之类的优点之一是您可以嵌入数据以减少在页面上运行所需的查询。通过缓存关注者计数,你正在做的是什么。

您的两个选项都有效,这只是您想要做出的权衡。

1)效率较低,但最准确。任何形式的异步都会在他们下次跟随某人时被修复。如果跟随者计数或用户数据库变大,这是一个很好的开始然后更改的方法。

2)效率最高,你需要确保在改变追随者数量时总是打电话给$ inc,否则在你做#1之前它会变得黯然失色。

或者,您可以执行#2,然后在后台运行一个对帐作业,该作业将重新同步,因为它可能会被拒绝。您可以使用MongoDB aggregation framework轻松完成此操作,您可以使用User集合中的时间戳加快对帐作业,并仅为自上次作业运行后更新的用户重新计算关注者。

随着原始问题的更新而扩展:

一般来说,如果你可以避免做count(),你应该。

开始使用count()然后交换到更高效的解决方案(#2)没有任何问题。在直接停止使用count()之前,将count()结果缓存为memcache也可用于减少性能问题。

答案 1 :(得分:-1)

不要害怕存储比您认为在文档中需要的数据更多的数据。当我开始思考mongo时,而不是RDMS时,我被解除了思考规范化所有内容。它允许我在文档中添加更多“有用”信息,即使它不是绝对必要的。文档中的事务是便宜的,并且存储的成本也相对便宜。在另一个文档或集合中查找信息的成本很高(处理方式),如果可以,可能值得减轻。

我理解您关于在数据库中计算“应用程序可以编辑”的问题。所以呢?确保您的应用程序无法对其进行编辑,如果您的API对全世界开放,请确保它们也无法编辑。 “缓存”计数的有用性远远超过了它可能被编辑并且不同步的事实。这是使用nosql数据库的危险之一:事情可能最终不同步,因为我们信任应用程序代码以保持数据的良好顺序,而不是依赖于数据库。

考虑一下。如果删除用户并且计数未更新,该怎么办?这会让世界对用户产生影响吗?可能不是。虽然我喜欢后台任务检查值的想法(并且值得拥有类似的东西),但另一种解决方案是每次用户向关注者发布内容时检查完整性。在这种情况下,你必须得到所有用户,所以检查计数也相对便宜。基本上,您构建的是故障安全,每次从用户发送消息时都会检查数据完整性。如果用户从未发送过,那么该用户可能并不关心计数是否100%准确。

在一天结束时,如果您的代码经过了充分测试,并且遵循防御性编码实践,则不应存在任何一致性问题。