2017-08-15 55 views
1

我需要在集合中標記文檔,我們稱之爲「聯繫人」。如何在MongoDB中標記文檔?

我的第一個想法是爲每個文檔創建一個名爲「tags」的屬性。 那麼,在這種情況下,我們有這樣的事:

{ 
_id:'1', 
contact_name:'Asya Kamsky', 
tags:['mongodb', 'maths', 'travels'] 
} 

現在,讓我們假設我們有希望在的「聯繫人」來標記任何文檔的用戶。

如果我們保留爲每個文檔保存標籤屬性的決定,由於標籤是個人的,我們需要爲每個標籤使用userId。 因此,我們的文件將是類似的東西(或沒有):

{ 
_id:'1', 
contact_name:'Asya Kamsky', 
tags:[ 
{userId:'alex',tags:['mongodb', 'maths', 'travels']}, 
{userId:'eric',tags:['databases', 'friends', 'japan']}, 
] 
} 

現在,讓我們開始有點複雜了。假設我們有很多用戶,並且每個用戶都想用他的個人標籤標記文檔。

如何處理?

好了,我們可以爲每個文檔創建成千上萬個標籤:

{ 
_id:'1', 
contact_name:'Asya Kamsky', 
tags:[ 
{userId:'alex',tags:['mongodb', 'maths', 'travels']}, 
{userId:'eric',tags:['databases', 'friends', 'japan']}, 
{.....................................................} 
{.....................................................} 
{......................................................} 
] 
} 

但是,如果我們有幾百萬的用戶?在這種情況下,我們對每個文檔都有16mg的限制,據我所知......

在這一點上,擔心我的應用程序的未來增長,我決定創建一個名爲'tags'的好分離集合,將包含類似於以下文檔:

{ 
    "contact_name" : "Asya Kamsky", 
    "useriId" : "alex", 
    "tags" : ['mongodb', 'maths', 'travels'], 
    "timestamp" : "2017-08-08 14:33:28" 
}, 

{ 
    "contact_name" : "Asya Kamsky", 
    "useriId" : "eric", 
    "tags" : ['databases', 'friends', 'japan'], 
    "timestamp" : "2017-08-08 14:33:28" 
} 

即,我們有一個分開的文檔,代表每個用戶的標籤。

清涼乾淨吧?

好了,我這種情況下,我們面臨兩個問題:

  1. 小問題:我們回到那個我不喜歡了的SQL邏輯,但我在某些情況下接受。
  2. 大(對我來說)問題:如何通過PERSONAL標籤搜索聯繫人?在這種情況下,我們有一個很好的'JOIN'問題,MongoDB使用$ lookup很好地解決了這個問題。 對於10000,20000乃至500000個文檔,「解決得好」。但由於我想確保未來的良好表現,我認爲約有1000萬個聯繫人。因此,正如我最近研究的那樣,$查找適用於宇宙的「小部分」,即使使用索引,這種搜索也需要很長時間才能執行。

如何解決這個挑戰?

感謝所有

回答

0

如果您的使用情況是這樣的,每個接觸number of users X number/size of tags(加任何其他數據在contacts文件)很可能給你帶來近16MB的文件大小限制,然後存儲標記INS一單獨收集似乎有效。但在你走下這條路線之前,你確定這可能嗎?您是否曾嘗試通過出價創建聯繫文檔來查看有多少標籤,每個聯繫人有多少用戶會使您接近16MB的限制。如果答案意味着你不可能達到的許多用戶和/或標籤,那麼也許你的擔心是嚴格的理論,你可以考慮堅持最簡單的解決方案,即在contacts內嵌入用戶特定標籤。

此答案的其餘部分假設尺寸估計值以及您對每個聯繫人的標籤和用戶的可能數量的瞭解,以確保尺寸限制是有效的。在此基礎上,您表達了對加入性能的具體關注......

但是,由於我想確保未來有良好的性能,我認爲約有1000萬個聯繫人。因此,正如我最近研究的那樣,$查找適用於宇宙的「小部分」,即使使用索引,這種搜索也需要很長時間才能執行。

您是否嘗試過測量此性能?生成contactstags的種子文檔,然後保留這些變體,然後使用$ lookup運行查詢並測量性能。你可以幾個基準做到這一點,例如:

  • 1000條聯繫人和10000個標籤
  • 100000聯繫人1,000,000標籤
  • 百萬聯繫人和10,000,000標籤
  • 10,000,000接觸及100,000,000標籤

運行基準測試時,您還可以使用explain()瞭解MongoDB內部發生了什麼。

您可能會發現性能是可以接受的,只有您能夠了解這一點,因爲您瞭解了系統用戶對性能的期望。

最後一點,如果用例這裏是一個給定的用戶要找到所有的聯繫人和標籤,然後這個可以以「客戶端聯接」,即處理兩個查詢(1)來獲得標籤"userId" : "..."和(2)查找這些標籤引用的聯繫人。取決於你的用例是什麼,這個可能是更高性能的服務器端加入(又名$查找)。

相關問題