通过String而不是ObjectId引用其他文档

时间:2013-09-23 02:26:58

标签: mongodb

假设我有两个集合:

ProductsCategories

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

  • _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(...)而不是字符串吗?

3 个答案:

答案 0 :(得分:1)

我认为这并不重要。

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

答案 1 :(得分:1)

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

  1. 无法将ObjectId与同一String值的ObjectId表示进行比较。因此,ObjectId("523c7df5c30cc960b235ddee")不等于"523c7df5c30cc960b235ddee"
  2. ObjectId,当本地存储时,将存储为12个字节,加上字段名称
  3. ObjectId作为字符串存储时,通常以24个字节存储(因为它将转换为十六进制数字),加上字段名称
  4. 使用12字节数可以更有效地进行比较,因为它比较的字节数更少。在大多数类型的使用中都没关系,所以这是微观优化(但你应该知道的事情)
  5. 奖励 - 如果你不使用简短的缩写字段名称,那么本地使用ObjectId作为12个字节的大小优势确实无关紧要,因为字段名称远远超过字节大小时存储为字符串。
  6. 我建议将它们存储为原生ObjectId。某些驱动程序可以选择并透明地转换为ObjectIdString并返回,以便客户端代码可以更轻松地操作它。例如,C#驱动程序可以执行此操作,并且我已经使用它,以便在序列化为JSON时,ObjectId采用易于在JavaScript中使用的简单格式。

答案 2 :(得分:0)

当您尝试从“类别”集合中查找产品的详细信息时,这将非常重要。

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

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

第一次这样做时感觉不对。毕竟,如果您更改了可能会或可能不会频繁出现的产品名称,则必须更新许多文档。您必须通过考虑应用程序使用它的方式来建模数据。

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

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

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

相关问题