Javascript 在MongoDB中用属性表示多对多关系的最佳模型
表示具有属性的多对多关系的最“mongo”方式是什么 例如: 简介Javascript 在MongoDB中用属性表示多对多关系的最佳模型,javascript,mysql,mongodb,meteor,nosql,Javascript,Mysql,Mongodb,Meteor,Nosql,表示具有属性的多对多关系的最“mongo”方式是什么 例如: 简介 MYSQL表 人=>名、姓、… 电影=>名称、长度.. peopleMovies=>movieId、人名、语言、角色 解决方案1 把人植入电影 在MongoDB中,我理解将非规范化并嵌入是件好事,但我不想将人嵌入电影,这在逻辑上毫无意义。因为人们不一定只属于电影 解决方案2 人物和电影将是两个独立的集合。 People=>embed[{movieId:12,personId:1,语言:“英语”,角色:“Main”}…] 电
MYSQL表
人
=>名、姓、…
电影
=>名称、长度..
peopleMovies
=>movieId、人名、语言、角色
解决方案1
把人植入电影 在MongoDB中,我理解将
非规范化并嵌入
是件好事,但我不想将
人嵌入电影,这在逻辑上毫无意义。因为人们不一定只属于电影
解决方案2
人物
和电影
将是两个独立的集合。
People
=>embed[{movieId:12,personId:1,语言:“英语”,角色:“Main”}…]
电影
=>嵌入[{movieId:12,personId:1,语言:“英语”,角色:“Main”}…]
此解决方案的问题是,当我们要为特定的电影
更新一个人的角色时,我们需要运行两个更新查询,以确保两个集合中的数据同步
解决方案3
我们还可以做一些关系性更强的事情,比如最终得到三个集合
人
=>名、姓、…
电影
=>名称、长度..
演员
=>电影ID、人物ID、语言、角色
问题是,由于MongoDB中缺少join语句,因此从people->movies开始需要3次查询
,反之亦然
这里是我的问题,在MongoDB
中,还有哪些其他方法可以以更NoSQL
的方式对类似的东西进行建模。就提供的解决方案而言,在mongo中,哪一个在性能和惯例方面最好。meteor的API在许多方面鼓励使用扁平关系文档,但是MongoDB是一个非关系数据存储。不幸的是,这一冲突留给开发人员解决
模式结构和连接的概念是一个需要在单个答案中涵盖的庞大主题,因此我将尝试尽可能简洁
选择关系模型的原因
假设您有评论和帖子数据。考虑如果你在你的文章中嵌入评论,将会发生什么。
- DDP对文件进行操作。每次在同一帖子中添加新评论时,都会发送所有评论
允许
和拒绝
规则对文档进行操作。期望同样的规则同时适用于帖子和评论可能是不合理的
- 出版物往往在收藏方面更有意义。在上述场景中,我们无法轻松发布独立于其帖子的评论列表
- 关系数据库的存在有很好的理由。其中之一是避免第二个解决方案中固有的多次修改问题
选择嵌入式模型的原因
- MongoDB本机不支持连接,并且没有生成反应连接的核心包
建议
使用第三种解决方案。根据我的经验,选择关系模型的原因远远超过了数据存储所施加的限制。当然,克服连接的缺乏并不容易,但痛苦可能只限于少数发布函数。以下是我极力推荐的一些资源:
- 在偶发的梦中。Chris详细介绍了您的具体用例,但是他使用observe回调手动执行反应式连接,我不推荐这样做
- 从。这涵盖了如何以及为什么应该进行反应式连接的基本知识
- 来自的非规范化章节。这涵盖了我上面提到的许多要点,还讨论了何时以及如何对一些数据进行非规范化
- 您可以使用来加入数据。其他软件包包括:、和
如果您需要更多信息,请在下面进行评论,我将更新我的答案。我认为您应该对您的收藏进行非规范化。设计MongoDB集合和文档时,重要的一点是考虑您的视图。显示视图需要哪些数据?其想法是,您应该尝试将这些数据作为文档的一部分
例如,在您的例子中,您可能有一个电影
视图,您希望在其中显示有关电影的信息。但是关于电影的页面可能只需要每个人的基本信息(名字、姓氏、照片URL)。不是所有其他的事情。反之亦然,关于一个人的页面可能会列出所有电影,但也同样只需要关于每部电影的信息子集,如标题、年份和海报照片URL
因此,一种选择是有两个集合,但然后在集合之间嵌入(非规范化)所需的那个些字段。例如,Movies
collection将有一个字段people
,它是一个子文档数组。而People
集合将具有movies
字段,该字段将是一个子文档数组,以及那些您想要指定角色的额外字段,依此类推
因此,文档可能如下所示。电影:
{
_id: "AAA",
title: "...",
year: 2015,
length: 120,
posterURL: "...",
people: [
{
person: {
_id: "BBB",
firstName: "...",
lastName: "...",
photoURL: "..."
},
role: "..."
}
]
}
{
_id: "AAA",
title: "...",
year: 2015,
length: 120,
posterURL: "..."
}
市民:
{
_id: "BBB",
firstName: "...",
lastName: "...",
photoURL: "...",
movies: [
{
_id: "AAA",
title: "...",
year: 2015,
posterURL: "..."
}
]
}
{
_id: "BBB",
firstName: "...",
lastName: "...",
photoURL: "..."
}
当然,问题是如何保持这些字段同步。如果您更新了电影的海报照片URL,那么您希望它在所有个人文档中也被更新。为了解决这个问题,我们开发了一个包来定义集合之间的关系,从而确保它们保持同步
因此,在您的情况下,我会在PeerDB中,在CoffeeScript中定义这样的集合:
class People extends Document
@Meta
name: 'People'
class Movies extends Document
@Meta
name: 'Movies'
fields: =>
people: [
person: @ReferenceField People, ['firstName', 'lastName', 'photoURL'], true, 'movies', ['title', 'year', 'posterURL']
]
<
{
_id: "...",
movie: {
_id: "AAA",
title: "...",
year: 2015,
posterURL: "..."
},
person: {
_id: "BBB",
firstName: "...",
lastName: "...",
photoURL: "..."
},
role: "..."
}
class People extends Document
@Meta
name: 'People'
class Movies extends Document
@Meta
name: 'Movies'
class Casting extends Document
@Meta
name: 'Casting'
fields: =>
person: @ReferenceField People, ['firstName', 'lastName', 'photoURL']
movie: @ReferenceField Movies, ['title', 'year', 'posterURL']