在MongoDB中建立朋友关系的朋友

时间:2011-09-12 23:43:54

标签: mongodb nosql

我们需要能够在用户的朋友和朋友的朋友之间快速执行查询。这在关系数据库中相对简单,但我有点坚持在MongoDB中完成它的最佳方法。我们将用户朋友的用户ID存储在用户文档中的数组中,因此显而易见的解决方案是:

  • 从用户文档中提取所有朋友用户ID
  • 从这些朋友的用户文档中拉出所有朋友数组(在所有朋友ID中使用$ in查询),将应用程序端组合成一个集合,然后将其与第一级朋友用户ID组合以获取所有朋友的集合朋友的朋友
  • 使用该集对所有朋友的朋友和朋友执行最终查询(使用$ in)

虽然直截了当,但与我们在关系数据库中的连接所做的相比,这看起来像是大量的来回。有没有更有效的方法在MongoDB中执行此操作,或者这是一个最适合RDBMS的问题?

3 个答案:

答案 0 :(得分:13)

我最近在MongoDB SV会议上向Eliot Horowitz提出了同样的问题。他说他构建它的方式是将每个用户朋友存储为每个用户的嵌入文档。例如,结构可能如下所示:

{
  _id : ObjectId("4e77bb3b8a3e000000004f7a"),
  username : "alex",
  friends : ["283956723823626626aa", "226567377578888888as", "8738783888aas88a8a88" ]
}

然后你可以在user.friends

上有一个索引

http://www.mongodb.org/display/DOCS/Indexes#Indexes-IndexingArrayElements

“当索引键字段的文档存储值是数组时,MongoDB会索引数组的每个元素。有关详细信息,请参阅”多键“页面。”

所以我可以找到所有“亚历克斯”的朋友:

db.user.find({'friends':'4e77bb3b8a3e000000004f7a'});

答案 1 :(得分:7)

  与我们在关系数据库中的连接相比,这看起来像是一个大量的来回

这一切都非常相对。你提取“朋友的朋友”的基本假设是正确的,它是一些跳跃和几个记忆中的“区别”。

然而,从“完成工作总量”的原始角度来看,这与您使用SQL的方式没有太大差别。是的,它是一个相对简单的SQL查询,但服务器本身仍然必须完成相同数量的工作,提供或占用一些网络流量。

  

在MongoDB中有更有效的方法吗,或者这是一个最适合RDBMS的问题?

MongoDB有更好的方法吗?可能不是。但是在SQL中进行“自联接”并不容易跨多个服务器进行扩展。实际上,尝试跨多个服务器执行此操作基本上会转换为与MongoDB进程类似的过程。

从技术上讲,这是一个图形数据库最好的工作,既不是MongoDB也不是RDBMS。

对于图表数据库,您可以查看Trinity for .NETNEO4J

答案 2 :(得分:2)

我认为这是由RDBMS(限制图形DB)更好地处理的事情,因为您显然需要执行“连接”操作。虽然RDBMS可能以相同的方式实现它,但它可以更有效地实现连接,并且比MongoDB更有效地分发信息。

话虽如此,如果你有一个庞大的数据库节点集群和大量用户,那么以原子方式执行“连接”查询的开销可能会成本太高。

如果您不担心查询的一致性和原子性,并且您想要的是阻止应用程序和数据库之间的来回,您可以编写一个JavaScript函数来执行整个查询MongoDB,或使用MapReduce操作进行更有效的分布式查询。