2011-09-12 62 views
17

我们需要能够快速地在一组用户的朋友和朋友的朋友中执行查询。这在关系数据库中会相对简单,但我在MongoDB中完成它的最佳方式有点困难。我们存储的用户的朋友的用户ID的用户文档中的数组,所以显而易见的解决方案是要做到这一点:在MongoDB中为朋友关系建模的朋友

  • 把所有来自用户的文档
  • 拉离用户文档的所有朋友阵列朋友的用户ID (在所有朋友ID中使用$ in查询),将应用程序端组合到一个集合中,然后将其与第一级朋友用户ID结合以获得所有朋友和朋友的朋友
  • 使用该设置为在所有朋友和朋友的朋友中执行最终查询(使用$ in)

虽然简单明了,但与我们在关系数据库中加入可以做的事情相比,这似乎是来回式的大量数据。在MongoDB中有没有更有效的方法来做到这一点,或者这是一个最适合RDBMS的问题吗?

回答

7

这似乎是一个巨大的回用量来回相比,我们可以在关系数据库中

与加盟做的这是非常相对的。你在获取“朋友朋友的朋友”的基本假设是正确的,这是几跳和一些内存“区别”。

但是,从“完成全部工作”的原始角度来看,这与您对SQL所做的工作并没有太大的不同。是的,这是一个相对简单的SQL查询,但服务器本身仍然必须执行基本相同的工作量,给予或采取一些网络流量。

在MongoDB中有更高效的方法来做到这一点,还是这是一个最适合RDBMS的问题?

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

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

对于图数据库,你可以看看Trinity for .NETNEO4J

2

我相信这是由RDBMS(禁止图DB)更好地处理,因为您显然需要执行“加入”操作。尽管RDBMS可能以同样的方式实现,但它可以更有效地实现连接,并比MongoDB更有效地分配信息。

即便如此,如果您有大量的db节点和大量的用户,那么以原子方式执行“连接”查询的开销可能会过高。

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

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索引数组的每个元素。请参阅Multikeys页面以获取更多信息。“

所以要找到所有的 “亚历克斯” 的朋友,我可以这样做:

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

+1

这假定朋友关系总是相互的......如果alex是jon的朋友,那么jon也必须是alex的朋友。 – Jay

+0

如何获得共同的朋友? –

+0

看看https://gist.github.com/levicook/4132037对于共同朋友 – rodi