2017-09-27 97 views
0

假设我们有以下类别:MongoDB的 - 如何正确建模关系

Users 
{ 
    "id": MongoId, 
    "username": "jsloth", 
    "first_name": "John", 
    "last_name": "Sloth", 
    "display_name": "John Sloth" 
} 

Places 
{ 
    "id": MongoId, 
    "name": "Conference Room", 
    "description": "Some longer description of this place" 
} 

Meetings 
{ 
    "id": MongoId, 
    "name": "Very important meeting", 
    "place": <?>, 
    "timestamp": "1506493396", 
    "created_by": <?> 
} 

后来,我们想返回(例如,从REST Web服务)这样的即将到来的事件列表:

[ 
    { 
     "id": MongoId(Meetings), 
     "name": "Very important meeting", 
     "created_by": { 
     "id": MongoId(Users), 
     "display_name": "John Sloth", 
     }, 
     "place": { 
     "id": MongoId(Places), 
     "name": "Conference Room", 
     } 
    }, 
    ... 
] 

重要的是返回需要显示在web ui主页上的基本信息(因此不需要额外的调用来呈现表)。这就是为什么,每个条目包含创建它的用户display_name以及该地点的name。我认为这是一个很常见的情况。

现在我的问题是:我应该如何将此信息存储在db(Metting文档中的问号值)?我看到2个选项:

1)店铺引用其他集合:

place: MongoId(Places) 

(+)数据始终是一致的

( - )额外调用数据库有为了进行构建响应

2)进行非标准化数据:

"place": { 
    "id": MongoId(Places), 
    "name": "Conference room", 
    } 

(+),无需额外的调用(响应可以根据一个文件来构造)

( - )数据必须每次相关的文件被修改

什么是处理的适当方式进行更新有这种情况?

如果我使用选项1),我应该如何查询其他文档?分别询问每个相关文档看起来像是过度杀伤。如何获得最后20次会议,汇总相关文件列表,然后执行如db.users.find({_id: { $in: <id list> }})这样的查询?

如果我选择2),我应该如何保持数据同步?

在此先感谢您的任何建议!

回答

0

由于MongoDB在3.2版中引入了$lookup aggregation,所以您可以保留已有的数据库模型,并且仍然只执行单个查询。这与加入RDBMS类似。

$查找

执行左外连接到unsharded集合在同一个数据库中的“加盟”收集处理文档进行过滤。 $ lookup阶段在输入文档的字段与“已加入”集合的文档中的字段之间进行平等匹配。

因此,不是存储对其他集合的引用,而是存储文档ID。

+0

我不知道部分“unsharded集合”。说实话,它现在对我很有用,因为我没有任何分片收藏。但是,如果相关集合被分割了,怎么办? – jbacic

+0

据我所知,没有其他方式分片收集https://stackoverflow.com/questions/34633111/mongodb-to-use-sharding-with-lookup-aggregation-operator。但是通常你必须存储一些数据并且有一些用户可以为分片辩护。 – str