假设我有一个名为Articles
的集合,如果我想向该集合中插入一个新文档,而没有为_id
字段提供值,MongoDB将为我生成一个特定于机器和操作时间的值(例如sdf4sd89fds78hj
)。
但是,我确实能够为MongoDB传递一个值,用作_id
键的值(例如1
)。
我的问题是,使用我自己定制的_id
有什么好处,还是最好让Mongo自己做?在什么情况下我需要分配一个定制的_id
?
- 更新**
一般的想法(据我所知)是给你自己的_id
赋值没有错,但是它迫使你在你的应用层(PITA)中维护唯一的值,并且需要在每个insert
之前进行额外的查询,以确保你不会意外地重复一个值。
Sammaye在这里提供了一个很好的答案:将MongoDB中的_id类型改为integer不好吗?
5条答案
按热度按时间9o685dep1#
生成您自己的
_id
的优势:t3oSKd9q
(That不会占用太多的屏幕空间,可以从列表中选择,如果需要,也可以手动复制。但是,您需要使它足够长,以防止冲突。)
_id
,它将相关对象分组到一个shard上,例如按所有者、地理区域或组合。(同样,这是否可取取决于您打算如何查询数据,和/或生成和存储数据的速度。您还可以通过指定一个shard键来实现这一点,而不是_id
本身(参见下面的讨论)。使用
ObjectId
的优点:_id
,那么您需要自己管理冲突风险。nanoid模块可以帮助你生成短的随机id,他们还提供了一个calculator,可以帮助你选择一个合适的id长度,这取决于你每小时生成多少文档/id。
或者,我编写了mongoose-generate-unique-key来生成 * 非常 * 短的随机id(假设您使用的是mongoose库)。
切分策略
注意:只有当你有大量的文档(或者非常重的文档)而不能被一个服务器管理时,才需要分片。它需要相当多的工作来设置,所以我建议你在确定你确实需要它之前不要担心它。
我不会声称自己是如何最好地分割数据的Maven,但下面是我们可能考虑的一些情况:
1.天文观测台或粒子加速器每秒处理数千兆字节的数据。当探测到有趣的事件时,他们可能希望在几秒钟内存储大量数据。在这种情况下,他们可能希望文档在碎片之间均匀分布,以便每个碎片都能同样努力地存储数据,而不会有任何一个碎片不堪重负。
1.您有大量的数据,有时需要同时处理所有数据。(但取决于算法)均匀分布可能再次是所期望的,使得在最后组合结果之前,所有碎片可以同样努力地处理它们的数据块。(尽管在这个场景中,我们可以依靠MongoDB的均衡器,而不是我们的shard密钥来实现均匀分布。均衡器在数据存储之后在后台运行。在收集了大量数据之后,您可能需要让它在夜间重新分配块。)
1.你有一个拥有大量数据的社交媒体应用程序,但这次许多不同的用户都在做许多轻微的查询主要与他们自己的数据,或者他们特定的朋友或主题有关。在这种情况下,每当用户进行一个小查询时就涉及每个shard是没有意义的,按userId进行shard可能是有意义的(或按主题或按地理区域),这样属于一个用户的所有文档都将存储在一个shard上,并且当该用户进行查询时,只有一个shard需要工作,这将使其他shard自由地为其他用户处理查询,因此可以同时服务许多用户。
1.如果您有许多查看相似时间段数据的简单查询,例如许多不同的用户查询不同的历史图表,则可能需要按创建时间(默认ObjectId将为您提供)分片文档。
但是如果你的大多数用户只查询最近的文档(这在社交媒体平台上很常见),这可能就不那么理想了,因为这意味着一个或两个碎片会占据大部分工作。按主题或地区分布可能会提供一个更平坦的整体分布,同时也允许相关文档聚集在一个碎片上。
您可能想阅读有关此主题的官方文档:
waxmsbnn2#
我可以想到一个很好的理由来预先生成你自己的ID。那就是幂等性。例如,这样就可以在崩溃后判断某个东西是否工作。当使用重试逻辑时,这个方法工作得很好。
让我来解释一下,人们考虑重试逻辑的原因是:应用之间的通信有时会因为不同的原因而失败(特别是在微服务架构中)。通过编写应用重试而不是立即给予的代码,应用将更具弹性和自我修复能力。这可以克服可能发生的意外情况,而消费者永远不会受到影响。
例如,当处理mongo时,一个请求被发送到数据库以存储某个对象,数据库保存了它,但是就在它试图响应客户端说一切正常时,不知什么原因出现了一个网络信号,并且从来没有收到“OK”。应用程序认为它没有工作,所以应用程序可能最终会重新尝试相同的数据并存储它两次,或者更糟的是它会爆炸。
预先创建ID是帮助处理重试逻辑的一种简单、低开销的方法,当然也可以考虑其他方案。
尽管这种弹性在某些类型的项目中可能有些过头,但这确实取决于具体情况。
x8goxv8g3#
我用过几次自定义ID,它非常有用。
特别是我有一个按日期存储统计数据的集合,所以
_id
实际上是一个特定格式的日期。我这样做主要是因为我总是按日期查询。请记住,使用这种方法可以简化索引,因为不需要额外的索引,基本的游标就足够了。wfypjpf44#
有时ID比随机生成的ID更有意义,例如,用户集合可能使用email地址作为_id。在我的项目中,我生成的ID比Mongodb使用的要短得多,因此URL中显示的ID也要短得多。
6yoyoihd5#
举个例子,我创建了一个财产管理工具,它有多个集合。为了简单起见,一些字段会重复,例如付款。当我需要更新这些记录时,它必须在所有集合中同时发生,所以我会为它们分配一个自定义付款ID,以便在执行删除/查询操作时,它会更改数据库范围内的所有示例