2011-09-12 60 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