MongoDb多对多,关系密切

MongoDb多对多,关系密切,mongodb,nosql,Mongodb,Nosql,我在Stackoverflow中阅读了很多文档和示例,但我并不确定我的结论,所以这就是我寻求帮助的原因 假设我们有一组电影和一组用户,我们想知道,哪些用户看过电影,哪些电影看过用户 在MongoDb中设计此功能的一种方法是: 用户: { "name":"User1", "films":[filmId1, filmId2, filmId3, filmId4] //ObjectIds from Films } 电影: 好的,如果用户/电影数量较低,这可能会起作用,但例如,如果我们预计一部电影将有8

我在Stackoverflow中阅读了很多文档和示例,但我并不确定我的结论,所以这就是我寻求帮助的原因

假设我们有一组电影和一组用户,我们想知道,哪些用户看过电影,哪些电影看过用户

在MongoDb中设计此功能的一种方法是:

用户:

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

好的,如果用户/电影数量较低,这可能会起作用,但例如,如果我们预计一部电影将有800k用户,那么阵列的大小将接近:800k*12字节~9.5MB,这接近BSON文件的最大16MB

在这种情况下,除了典型的关系世界方法之外,还有其他方法,即为关系创建一个中间集合

另外,我不知道与经典的关系方式相比,读取和解析大约10MB的JSON是否会有更好的性能


谢谢你的电影,如果你包括观众,你可能最终会找到答案,正如你正确地说的那样

根据您的使用案例,将用户看过的电影放入阵列是一种可行的方法。特别是如果您想与属性(比如查看日期和地点)建立关系,那么更新和统计分析的性能就会降低(您需要先您的文档,然后的成本会更高等等)

如果您的关系具有或可能具有属性,我将采用您所描述的经典关系方式,因为它与嵌入一样能够很好地回答您最可能的用例,并从我的经验中获得更高的性能:

给定一个具有如下结构的集合

 {
   _id: someObjectId,
   date: ISODate("2016-05-05T03:42:00Z"),
   movie: "nameOfMovie",
   user: "username"
 }
您可以随时轻松回答以下示例问题:

  • 对于给定的用户,他在过去3个月里看过哪些电影,按日期降序排列

    或者,如果您可以使用迭代器,则使用以下工具更容易:

    db.views.find({user:username, date:{$get:threeMonthAgo}}).sort({date:-1})
    
  • 对于一部电影,今年5月30日有多少用户看过

    我在这里使用聚合而不是对结果使用.count()的原因是

  • 对于给定的电影,显示所有看过它的用户


  • 有一点需要注意:因为我们分别使用了用户名和电影名,所以我们不需要一个JOIN(或类似的东西),这应该会给我们带来良好的性能。此外,在添加条目时,我们不必执行代价高昂的更新操作。我们不需要更新,只需插入数据。

    对于电影,如果你包括观众,你最终可能会点击屏幕,正如你正确指出的那样

    根据您的使用案例,将用户看过的电影放入阵列是一种可行的方法。特别是如果您想与属性(比如查看日期和地点)建立关系,那么更新和统计分析的性能就会降低(您需要先您的文档,然后的成本会更高等等)

    如果您的关系具有或可能具有属性,我将采用您所描述的经典关系方式,因为它与嵌入一样能够很好地回答您最可能的用例,并从我的经验中获得更高的性能:

    给定一个具有如下结构的集合

     {
       _id: someObjectId,
       date: ISODate("2016-05-05T03:42:00Z"),
       movie: "nameOfMovie",
       user: "username"
     }
    
    您可以随时轻松回答以下示例问题:

  • 对于给定的用户,他在过去3个月里看过哪些电影,按日期降序排列

    或者,如果您可以使用迭代器,则使用以下工具更容易:

    db.views.find({user:username, date:{$get:threeMonthAgo}}).sort({date:-1})
    
  • 对于一部电影,今年5月30日有多少用户看过

    我在这里使用聚合而不是对结果使用.count()的原因是

  • 对于给定的电影,显示所有看过它的用户


  • 有一点需要注意:因为我们分别使用了用户名和电影名,所以我们不需要一个JOIN(或类似的东西),这应该会给我们带来良好的性能。此外,在添加条目时,我们不必执行代价高昂的更新操作。我们不需要更新,只需插入数据。

    您能详细说明为什么要在胶片文档中保留用户引用吗?我想写的是一篇关于4种可能性的小文章,这4种可能性对你来说可能是真的,也可能不是真的:)你能详细说明一下为什么你想在电影文档中保留用户参考资料吗?我想写的是一篇关于4种可能性的短文,这4种可能性对你来说可能是真的,也可能不是真的:)非常感谢你的回答:)非常感谢你的回答:)
    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}
     }}
    ])
    
    db.views.find({movie:movieName},{_id:0,user:1})