一对多 Mongoose 关系 - 存储参考的位置
Posted
技术标签:
【中文标题】一对多 Mongoose 关系 - 存储参考的位置【英文标题】:One-to-Many Mongoose relationship - Where to store the reference 【发布时间】:2016-05-02 03:57:40 【问题描述】:我正在为一个新项目设计 MongoDB 集合架构,作为 MongoDB 新手,我有一个关于一对多关系的问题。
为了这个例子,假设关系是数据中心到服务器,这意味着一个数据中心可以有多个服务器(数千个,在应用程序中不限制),服务器只能属于一个数据中心。
最好让Servers._datacenter
引用Datacenter._id
吗?还是一个 Datacenter.servers
array 来存储服务器 ID?
如果您建议在 Datacenter 文档中使用 array 来引用与之关联的服务器 ID... 那么有没有办法在您刚刚拥有时找出服务器所属的 Datacenter服务器ID? (有点像快速的where serverId in Datacenter.servers
查询)无需查询每个数据中心,然后检查每个 Datacenter.servers 数组中的 ID
如果您建议在 Servers 文档中包含一个元素来引用它所属的 Datacenter,那么有没有办法查询 Datacenter,并在虚拟 Documents.servers 数组或其他东西中返回所有关联的 Server 文档?
我不太确定最好的方法是什么,因为每个数据中心可能有非常大量的服务器,我认为在每个数据中心文档中没有这么大的数组可能是一个更好的主意。 .. 但是,如果我将其设置为每个服务器文档中都引用了父数据中心,这会使查询变得相当困难(或者不是?也许有一个我还没有发现的非常简单的方法,我确实说过我是Mongo 新手)
我正在阅读this document,它显示了如何向上设置参考方向,并指出:
为避免可变的、不断增长的数组,请将出版商引用存储在图书文档中
这让我觉得最好在服务器文档中引用数据中心 ID。如果是这样,有没有办法将所有服务器文档作为数据中心文档中的数组返回?或者我是否必须查询数据中心,然后查询具有该数据中心._id 的所有服务器,然后返回一个合并对象..
【问题讨论】:
这取决于您的用例和您的 UI 屏幕? UI 屏幕是什么意思?你要截图吗? 【参考方案1】:这取决于访问模式。您打算如何将其编码为 null1941 所说的。
如果服务器的数量为 10 或数百台,我猜这将是 一对少的关系,而不是一对多的关系,因此您可以继续将数据中心嵌入服务器中。这意味着您将在一次查询中获得所需的所有信息。 如果您可以保证一致性,这种方法可能会奏效,但鉴于一个数据中心中存在许多服务器,您最终会出现重复。因此数据中心文档可以在许多服务器文档中复制。如果您再次可以保证一致性并且数据中心可能没有关于它们的信息,那么这种方法可以工作。这种方法的唯一优点是您只执行一个查询。 通常这种方法不推荐;此外,如果您想将数据中心视为一个单独的文档,以便对其运行一些操作而不是避免这种方法。
如果您决定采用这种方法;将数据中心嵌入为数组您可以使用 $all 或 $in 在数组内进行搜索。
示例:
"_id" : ObjectId("63546464sad65s4ad3654"),
"name" : "Server1",
"datacenter" : ["gamma", "500"]
查询:
db.users.find( "datacenter": $in: [ "gamma", "delta" ] )
如果您决定将服务器作为文档嵌入(您也可以将数据中心文档嵌入到服务器中,两者都可以工作)。因此,对于在数据中心文档中嵌入服务器,您可以使用点符号在嵌入文档中进行搜索。示例:(servers 是字典,name 是服务器内部的一个属性):
"_id" : ObjectId("63546464sad65s4ad3654"),
"name" : "gamma",
"servers" : [
"title" : "server1",
"speed" : "3.2GHZ",
"ram" : "200GB"
,
"title" : "server2",
"speed" : "3.2GHZ",
"ram" : "64GB"
]
查询:
db.datacenters.find( "servers.title": "server1"
你再次判断。但是,您决定这样做,在 mongodb 中有一种方法可以检索您需要的信息。
现在请记住,如果您决定在数据中心文档中嵌入服务器,那么在 mongodb 中,单个文档不应超过 16MB。如果通过嵌入可以超过此大小,则应采用拆分方法(如下)。
现在对您的更好的方法是不嵌入的情况;基本上正如 gnerkus 所说。但是请记住,在 mongodb 中没有外键约束,您必须确保使用应用程序的一致性。这样数据中心集合中的 server_id 可以在服务器集合中找到(反之亦然)。您还可以将 datacenter_id 放在服务器集合中;我决定选择哪一个的方式是我的用例。例如,如果我的大部分操作都在数据中心上,我将向其中添加 server_id。如果我的大部分操作都在服务器集合上,我将向其中添加 datacenter_id。在这两种情况下,您都将执行两个或多个查询。这是一个例子:
数据中心文档示例
_id : ObjectId("10001000010000"),
name : 'Gamma',
location: 'pluto',
servers: [
ObjectID('1212'),
ObjectID('1213')
]
服务器文档示例:
_id : ObjectId("1212"),
name : 'Server1',
ram: '250GB',
type: 'processing',
status: 'running'
在这种情况下,您可以查询为:首先您获得所需的数据中心(假设名称是唯一的)
datacenter = db.datacenter.findOne(name: "Gamma")
然后您将查询您需要的服务器的详细信息;获取上面给定数据中心中所有服务器的示例
servers = db.servers.find(_id: $in : datacenter.servers )
拥有所有服务器后,您可以遍历每个服务器并检查状态或其他内容。您最终将在 servers 变量中拥有服务器文档。
希望对你有帮助
【讨论】:
> 如果服务器的数量是 10 或数百个,我猜这将是一对少的关系,而不是一对多的关系,因此您可以继续将 DC 嵌入服务器中。这意味着您将在一次查询中获得所需的所有信息。 ---- 任何人都可以使用它,而且它很可能不止几百个,我喜欢设计这个来容纳 100k 或更多。 (我将围绕它进行负载测试)我认为在您的第三个代码 sn-p 中,数据中心 - > 服务器是向后的?至少对于我的例子。这将是一个 DC -> 许多服务器 所以知道它不仅仅是 10 或数百......你会建议什么样的关系结构? (我讨厌这里的回复字符限制,总是太短了..哈哈) 对于我的第二个示例(服务器内部的数据中心)是故意的,因为增长的是服务器,而数据中心(我假设)不会包含太多信息,可能只是它的名称或其他东西;这会奏效。不推荐这种方法,但可以工作。为什么不建议这样做是因为这为不一致和重复打开了空间(我将更新我的回复以涵盖这一点)。 在您的情况下,我建议您进行真正的链接。第三个选项将 datacenter_id 添加到服务器集合。我将用一些代码更新我的回复来解释这一点。 我稍微改了一下解释;并添加了您提到的注释。【参考方案2】:最好在 Server 文档中引用 Datacenter ID。要检索具有指定数据中心 ID 的服务器,您只需查询服务器集合。查询不难,如下所示:
var dataID = datacenter._id
db.servercollection.find( datacenter: dataID , function(err, servers)
);
【讨论】:
谢谢。我开始认为这也是最好的方法。尤其是@ibininja 关于 16MB 限制的评论。至于查询。我知道如何进行基本的查找查询,我更多的是指同时查询数据中心及其服务器的可能性(有点像子查询),但我认为只需运行两个查询和加入结果..无需过于复杂以上是关于一对多 Mongoose 关系 - 存储参考的位置的主要内容,如果未能解决你的问题,请参考以下文章
如何处理一对多关系中的嵌套 mongoose 查询和异步问题?