我在Stackoverflow中已经阅读了很多文档和示例,但我不确定我的结论,所以这就是我要求帮助的原因。
想象一下,我们有一个集合电影和一个集合用户和我们想知道,哪些用户看过一部电影,哪些电影见过用户。
在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 :(得分:2)
对于电影,如果你包括观众,你最终可能会按照正确的说法点击16MB size limit of BSON documents。
根据您的使用情况,将用户看到的电影放入阵列是一种可行的方法。特别是如果你想与属性(比如日期和观看地点)建立关系,那么做更新和统计分析会降低性能(首先需要 $unwind
你的文档,后续 $matches
变得更加昂贵,等等。
如果您的关系具有或可能具有属性,我会使用您所描述的经典关系方式,因为它可以回答您最有可能的用例与嵌入一样好,并允许我的经验具有更高的性能: / p>
给定一个像
这样的结构的集合 {
_id: someObjectId,
date: ISODate("2016-05-05T03:42:00Z"),
movie: "nameOfMovie",
user: "username"
}
您可以随时轻松回答以下示例问题:
对于给定的用户,他在过去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})
对于某部电影,有多少用户在今年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
对于给定的电影,请显示所有看过它的用户。
db.views.find({movie:movieName},{_id:0,user:1})
有一点需要注意:由于我们分别使用了用户名和电影名称,因此我们不需要JOIN(或类似的东西),这应该会给我们带来良好的性能。此外,添加条目时我们不必进行相当昂贵的更新操作。我们只是插入数据而不是更新。