mongodb - 用于在Web应用程序中实现类似功能的模式

时间:2013-02-04 07:36:51

标签: mongodb database nosql

我有一个mongodb数据库,我有2个收藏。 postsusers

帖子json结构就像

{title:"Title", content:"content goes here", postedby: "userid"}

和用户就像

{username:"", name:""}

现在我需要实现一个类似的功能,用户喜欢帖子。

解决方案1 ​​

我可以在像

这样的用户中放置一个内部数组
{username:"", name:"", likes:[postid1,postid2..]}

这里的问题是它易于查询用户喜欢的帖子。但很难找到喜欢文章的人。

解决方案2

我可以将内部数组放在像

这样的帖子中
{title:"Title", content:"content goes here", postedby: "userid", like:[userid1,userid2 ..]}

这里的问题是很容易让喜欢文章的人。但很难查询用户喜欢的帖子。

我该如何解决这个问题? 目前我正在考虑两种方式。就像在两个集合中保留内部数组一样。我知道我保留了冗余数据,这是解决这个问题的最佳方法吗?

3 个答案:

答案 0 :(得分:7)

我个人不会在这里找一个类似的数组。

喜欢失去控制的人太喜欢太多的帖子;到这可能会阻碍您可以存储在该文档中的顶级用户数据量。

您还必须在此处考虑您的查询模式。您很可能希望在多个用户之间进行某种类似的图表聚合。目前要动态地执行此类操作,您必须使用聚合框架:http://docs.mongodb.org/manual/applications/aggregation/(预聚合报告:http://docs.mongodb.org/manual/use-cases/pre-aggregated-reports/也将是一个有用的工具,但我将跳过这一点)使用$unwind

$unwind是一种内存中操作,对于许多用户的远程聚合而言可能很慢,特别是如果每​​个用户至少有1000个喜欢(50x1000已经在推动$unwind的内存限制和帖子$group $sort,其内存限制为系统内存的10%。总而言之,聚合框架不会用于查询这些喜欢的方法。

MongoDB可以很容易地存储这个结构,因为子文档对于每个条目可能是12个字节,所以你可以使用2个大小(http://docs.mongodb.org/manual/reference/command/collMod/#usePowerOf2Sizes)分配来解决你需要的问题。通常使用结构获得(碎片)。

所以考虑到这一点,我会把喜欢留在一个单独的集合中。确实,您将失去在用户文档中保留喜欢的单一往返符号,但我相信我上面所说的是物有所值。

答案 1 :(得分:5)

要问自己的重要问题是获取此数据需要哪些不同的方式?

可以在第一种情况下使用user.find({"likes":postId})查询喜欢特定网页的用户,并在第二种情况下查询相反的查询。但这是个好主意吗?您希望避免在MongoDB中持续增长文档,您可能不希望知道特定用户所有他们喜欢的页面,以及特定页面所有用户喜欢它。

那么如何在自己的集合中保存喜欢并且只保留用户和页面集合中的聚合(即计数)呢?您还可以选择在页面中保留最新的“N”类似内容,或者对您的应用程序及其性能最有用的其他内容。

很少有可能在不知道用例(即读取和写入模式)以及周围要求的情况下在MongoDB中设计“理想”模式。

答案 2 :(得分:3)

我认为只在发布文档中保留喜欢的数组就足够了。

您可以使用like字段获取用户喜欢的帖子。如果你在like字段上有索引,那么性能也会很好。

唯一的缺点是,使用这种方法,post对象的大小根据like数组的长度而变化。 Mongo不是很擅长处理这类数据结构,所以如果你有数千个喜欢的帖子保持所有的ID可能会降低查询的性能,但一般帖子没有那么多的喜欢和整体你的我相信系统会正常工作。您可能会考虑限制帖子的喜欢ID数量(例如,保留最后1000个用户ID)以确保文档的大小不会异常增长。