2016-05-31 99 views
0

我已經在Stackoverflow中閱讀了很多文檔和示例,但我並不確定我的結論,所以這就是爲什麼我要求幫助。MongoDb多對多有很大的關係

想象一下,我們有一個集合電影和一個集合用戶和我們想知道,哪些用戶看過一部電影,哪些電影看過一個用戶。 MongoDB中設計這個

的一種方式是:

用戶:

{ 
"name":"User1", 
"films":[filmId1, filmId2, filmId3, filmId4] //ObjectIds from Films 
} 

膜:

{ 
"name": "The incredible MongoDb Developer", 
"watched_by": [userId1, userId2, userId3] //ObjectsIds from User 
} 

沒關係,這可以工作,如果用戶/膜的量是低的,但是例如,如果我們預計一部電影將有800k用戶,則陣列的大小將接近:800k * 12字節〜9.5MB,這接近BSON文件的最大16MB。

在這種情況下,除了創建關係的中間集合的典型關係世界方式之外,還有其他方法嗎?

另外我不知道如果閱讀和解析一個約10MB的JSON將會有比傳統關係方式更好的性能。

謝謝

+0

你能否詳細說明你爲什麼要在電影文檔中保存用戶引用?我想寫的東西變成了一篇由我組成的4種可能性的小文章,對你來說可能是也可能不是這樣:) – malarzm

回答

2

爲電影,如果包括觀衆,你可能最終擊中16MB size limit of BSON documents,因爲你正確地指出。

根據您的使用情況,將用戶看過的電影放入陣列是一種可行的方法。特別是如果你想與屬性關係(比如日期和地點觀看),做更新和統計分析變得更高性能的(你需要$unwind您的文檔第一,隨後$matches變得更加昂貴和諸如此類的東西)。

如果你的關係已經或者可能具有的屬性,我會去與你形容爲古典關係的方式,因爲它回答的嵌入好你最有可能使用情況,並允許從我的經驗更高的性能:

給定的集合,其結構像

{ 
    _id: someObjectId, 
    date: ISODate("2016-05-05T03:42:00Z"), 
    movie: "nameOfMovie", 
    user: "username" 
} 

您手邊一切可以輕鬆地回答以下示例問題:

  1. 對於給定的用戶,他在過去3個月中看過哪些電影,按日期降序排列?

    db.views.aggregate([ 
        {$match:{user:userName, date:{$gte:threeMonthAgo}}}, 
        {$sort:{date:-1}}, 
        {$group:{_id:"$user",viewed:{$push:{movie:"$movie",date:"$date"}}}} 
    ]) 
    

    ,或者,如果您沒有問題的迭代器,甚至更容易:

    db.views.find({user:username, date:{$get:threeMonthAgo}}).sort({date:-1}) 
    
  2. 對於給定的電影,有多少用戶今年已經看到了5月30日?

    db.views.aggregate([ 
    {$match:{ 
        movie:movieName, 
        date{ 
        $gte:ISODate("2016-05-30T00:00:00"), 
        $lt:ISODate("2016-05-31T00:00:00")} 
    }}, 
    {$group:{ 
        _id: "$movie", 
        views: {$sum:1} 
    }} 
    ]) 
    

    爲什麼我在這裏使用的,而不是對結果的.Count中()聚集的原因是SERVER-3645

  3. 對於給定的電影,顯示其已經看到它的所有用戶。

    db.views.find({movie:movieName},{_id:0,user:1}) 
    

還有就是要注意一件事:因爲我們所使用的用戶名和電影的名字,分別爲,我們並不需要一個連接(或類似的東西),這應該給我們良好的性能。另外,添加條目時,我們不必進行昂貴的更新操作。我們只需插入數據,而不是更新。

+0

非常感謝你的迴應:) – pianista