【问题标题】:mongoid create 2 embedded document with the same mongo "_id"mongoid 创建 2 个具有相同 mongo“_id”的嵌入文档
【发布时间】:2015-05-06 12:25:19
【问题描述】:

我有一个 mongodb 记录,其中一个字段是两个相同的嵌入文档的数组(即使“_id”是相同的),这是否有意义。

我在使用 mongoid 创建记录时遇到了这个问题。我对 mongoid 的嵌入式文档实现了解不多,但我猜如果这些嵌入式文档是“文档”,它们都不应该有一个已经被另一个文档使用的“_id”。

我得到的一个例子:

{
   _id: "123",
   name: "sylvain",
   friends: [ ]
},
{
   _id: "245",
   name: "sonia",
   friends: [ {
      _id: 123,
      name: "sylvain"
   },
   {
      _id: 123,
      name: "sylvain"
   } ]
},
{
   _id: "456",
   name: "bob",
   friends: [ {
      _id: 123,
      name: "sylvain"
   } ]
}

【问题讨论】:

  • 是的,_id 应该是唯一的
  • @apneadiving,“应该是独一无二的”是什么意思?重复 _ids 情况有意义还是不应该发生?
  • 我觉得没有意义
  • @muistooshort,mongoid 分配它
  • @muistooshort,这正是我的问题......

标签: ruby-on-rails ruby mongodb mongoid


【解决方案1】:

为了说清楚:

  • _id 字段是集合的每个 文档上的必填项。它用于唯一地识别您的文档。将其视为您收藏的主键。 _id 字段总是有一个索引。
  • 通常,嵌入文档没有唯一标识符(他们根本不需要:嵌入文档实际上是其父文档的一部分——这不是关于两个“加入”集合)。
  • 但是,例如,您可以在嵌入文档中添加一个 id 字段作为外键。即使这可能相当混乱,如果您愿意,您甚至可以将其称为_id。但是,它在这种情况下不会有任何特殊含义。

由于 NoSQL 数据库倾向于使用非规范化模式,因此在 MongoDB 中将相同的文档嵌入到不同的根文档中是很常见的。事实上,这是表示多对多关系的一种方式。


这是一个完全有效的示例(即使,正如我之前所说,使用 _id 作为字段名称乍一看可能会令人困惑):

{
   _id: "123",
   name: "sylvain",
   friends: [ ]
},
{
   _id: "245",
   name: "sonia",
   friends: [ {
      _id: 123,
      name: "sylvain"
   } ]
},
{
   _id: "456",
   name: "bob",
   friends: [ {
      _id: 123,
      name: "sylvain"
   } ]
}


关于在 same 父文档中嵌入 两个 相同的文档:这可能是一种“计算”从父文档到子文档的引用数量的方法。把你的父子文档关系想象成一个图表。您很可能有两个从一个节点到另一个节点的链接——另一方面,人们会考虑向嵌入文档添加一些“权重”字段(因此,限定 链接)。根据您的用例,这两种解决方案可能各有利弊。

这是一个使用两个不同模型表示以下事实的示例:

“客户sylvain目前持有两张在我们商店免费下载MP3的优惠券”

// customer
{
   _id: "123",
   name: "sylvain",
   coupons: [ {
        _id: 9905,
        desc: "Free MP3 download"
   },
   {
        _id: 9905,
        desc: "Free MP3 download"
   } ]
}

或者,人们可能会这样想:

// customer
{
   _id: "123",
   name: "sylvain",
   coupons: [ {
        _id: 9905,
        desc: "Free MP3 download",
        qty: 2
   } ]
}

就我自己而言,我认为后者是否真的优于前者并不是那么明显。例如,在后一种情况下,当客户使用优惠券时,您将不得不decrease the qty -- and remove the coupon if qty == 0。似乎比前一种情况需要更多的工作。但是YMMV。

【讨论】:

  • 嗨,你描述的收藏不是我的情况。我在我的问题中附上了我的数据库中的一个示例。
  • @benams 感谢您澄清了这一点。我已经在我的回答中添加了几段。
  • 使用 Mongoid,嵌入文档是 Mongoid::Documents,就像根文档一样。所以嵌入文档得到_ids,就像其他所有文档一样,因为,好吧,ODM 也想要它们,而_ids 使“真实”关系的错觉更好(即你可以说o.embeddeds.find(id),就像你想的那样在关系系统中说o.relateds.find(id))。当然,如果您愿意,您可以手动使用哈希数组而不是 Mongoid 包装的嵌入式文档。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2013-11-14
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多