如何解决MongoDB中的“Digg”问题

3
一段时间以前,Digg的一位开发人员发布了这篇博客 "http://about.digg.com/blog/looking-future-cassandra",其中描述了MySQL中未被最优解决的问题之一。这被引用为他们转向Cassandra的原因之一。
我一直在使用MongoDB,我想了解如何实现这个问题的MongoDB集合。
根据文章,在MySQL中,此信息的架构如下:
CREATE TABLE `Diggs` (
  `id`      INT(11),
  `itemid`  INT(11),
  `userid`  INT(11),
  `digdate` DATETIME,
  PRIMARY KEY (`id`),
  KEY `user`  (`userid`),
  KEY `item`  (`itemid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `Friends` (
  `id`           INT(10) AUTO_INCREMENT,
  `userid`       INT(10),
  `username`     VARCHAR(15),
  `friendid`     INT(10),
  `friendname`   VARCHAR(15),
  `mutual`       TINYINT(1),
  `date_created` DATETIME,
  PRIMARY KEY                (`id`),
  UNIQUE KEY `Friend_unique` (`userid`,`friendid`),
  KEY        `Friend_friend` (`friendid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这个问题在社交网络场景的实现中是普遍存在的。人们结识了很多朋友,而这些朋友也会点赞很多东西。快速向用户展示他/她的朋友正在做什么非常关键。
我知道有几篇博客提供了一个针对这个问题的纯RDBMs解决方案,包括索引;然而我很好奇如何在MongoDB中解决这个问题。
2个回答

1
一种实现这个的方法是在每篇文章中添加一个“朋友”数组。
{
  date: Date(...)
  friends: ['me', 'you', 'thatguy']
  ...
}
db.posts.ensureIndex({friends:1, date:-1})

然后你可以通过以下方式轻松显示我的页面: db.posts.find({friends:'me'}).sort({date:-1})

只要每个用户的好友少于约200,000个,这将起作用;您可能需要特殊处理具有超过该数量的好友的用户的帖子。一种方法是将好友列表分成多个100,000个块,并为每个块创建一个帖子条目。


我假设在你的例子中,“friends”是一个对其他用户引用的数组。我假设这些用户存储在一个用户集合中,“friends”数组仅仅是用户集合中用户的引用列表。所以,如果我想找到我所有朋友的帖子,难道不需要进行“连接”吗?(我很抱歉使用加入等术语,因为我来自SQL背景)。 - user193116
朋友应该是您在用户对象中使用的_id的数组。这可以是字符串或ObjectID;两者都有优缺点。我不会执行类似于连接的操作。相反,只需将当前用户的_id存储在cookie或会话对象中。然后,只需在我的示例查询中替换字符串“me”为当前用户的_id,它就会实现您想要的功能。默认情况下,如果您使用查询中的单个值查询数组字段,则mongo将检查查询值是否在数组中。 - mstearn
谢谢!! 我会尝试这个解决方案。 - user193116

1

使用Mongo有许多可能的解决方案。您仍然可以像关系型数据库一样将diggs存储在顶级表(即集合)中,但还可以将diggs作为数组存储在item集合或user集合中。同样,朋友关系可以在用户集合中以正向或反向方式保留为数组。

最直接的方法可能是在items中使用diggs数组,在users中使用friends数组。然后,通过对索引的查询来检索用户的朋友,接着在索引的items.diggs.userid字段上进行“in”查询。

Mongo自己的文档$in operator实际上就使用了这个例子。


对于 Digg 来说,“in” 查询是个问题。朋友列表来自 MemCached,他们进行了一个“in”查询,这是一个瓶颈。(根据我使用 SQL 中的 'in' 的经验,它不是查询的最优方式)。从你的经验来看,$in 运算符的性能如何,假设有大约 50 个值要在“in”集合中使用? - user193116

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接