【问题标题】:Referencing Other Documents by String rather than ObjectId通过字符串而不是 ObjectId 引用其他文档
【发布时间】:2013-09-27 20:37:23
【问题描述】:

假设我有两个集合:

ProductsCategories

后一个集合的文档有2个字段:

  • _id (BSON ObjectId)
  • 名称(字符串)

后一个集合的文档有3个字段:

  • _id (BSON ObjectId)
  • 名称(字符串)
  • 产品(字符串数组)

假设我有以下Product 文档:

{ "_id" : ObjectId("AAA"), "name" : "Shovel" }

假设我有以下Category 文档:

{ "_id" : ObjectId("BBB"), "Name" : "Gardening", "Products" : ["AAA"] }

出于本示例的目的,假设 AAABBB 是合法的 ObjectId - 示例:ObjectId("523c7df5c30cc960b235ddee") 其中它们等于内部 ObjectId 的字符串。

应该将Products 字段存储为ObjectId(...) 而不是字符串?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    我认为这并不重要。

    我很确定 ObjectId 格式会编码一个十六进制数字,因此它在内存和带宽方面的效率可能会稍高一些。我已经做到了两种方式。只要您决定,对于每个字段,您将如何对其进行编码,任何一个都可以正常工作。

    【讨论】:

      【解决方案2】:

      当您尝试从 Categories 集合中查找产品的详细信息时,这一点最为重要。

      由于 Mongo 中没有服务器端 JOIN,因此您的代码必须将文档匹配在一起。 ObjectIDs are encoded as 12 bytes,您可以轻松地用任何语言进行比较。使用字符串或对象 ID 并不重要。

      您面临的真正问题是数据规范化(或缺乏规范化)之一。如果您将Name 字段存储在您的Categories 文档中,而不是ObjectID,您将能够在一次调用中返回产品名称(而不是多次调用,该类别的每个产品1 个)。

      第一次做的时候感觉不对。毕竟,如果您更改产品名称,您将不得不更新许多文档,这可能会也可能不会经常发生。您必须通过考虑应用程序使用数据的方式来对数据进行建模。

      最后,索引Prodcuts 集合中的Name 属性。从Categories 文档中找到的字符串开始获取产品的详细信息会很快。

      另一种方法是根本没有 Categories 集合,而是在您的 Products 文档中添加一个 Category 属性。您可以找到带有{'Category':'Gardening'} 的文档。索引Category 字段可能是个好主意。

      同样,ObjectID 或 String 并不重要。它是关于建模您的数据并考虑您的应用程序将如何使用它。

      【讨论】:

      • 回应:If you store the Name field ... in a single call" - I could achieve the same if I properly use an ObjectId(...)` 而不是String,对吧?
      • 如果您想在一个类别中显示产品的名称,则不是。我想您的应用程序将显示类别,并提供可供选择的产品名称列表。你已经有了名字。我会用另一种方式更新答案。
      【解决方案3】:

      只要您始终使用相同的类型(以便正确进行比较),区别在于:

      1. 不能将ObjectId 与具有相同ObjectId 值的String 表示进行比较。因此,ObjectId("523c7df5c30cc960b235ddee") 不等于 "523c7df5c30cc960b235ddee"
      2. ObjectIds,原生存储时,会被存储为 12 个字节,加上字段名
      3. ObjectId,当存储为字符串时,通常以 24 个字节存储(因为它将被转换为十六进制数字),加上字段名称
      4. 使用 12 字节数字可以更高效地进行比较,因为它比较的字节更少。不过,这在大多数类型的使用中都无关紧要,所以这是一个微优化(但你应该知道的)
      5. 红利——如果你不使用简短的字段名称,使用 ObjectId 本身作为 12 个字节的大小优势真的无关紧要,因为字段名称将远远超过存储为时的字节大小一个字符串。

      我建议将它们存储为原生 ObjectIds。一些驱动程序可以选择性地和透明地将ObjectId 转换为String 并返回,以便客户端代码可以更轻松地对其进行操作。例如,C# 驱动程序可以做到这一点,我已经使用它,以便在序列化为 JSON 时,ObjectId 是一种易于在 JavaScript 中使用的简单格式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-11
        • 1970-01-01
        • 1970-01-01
        • 2012-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-13
        相关资源
        最近更新 更多