哪个mongo文档架构/结构是正确的?

时间:2014-09-15 14:35:09

标签: mongodb

我有两种文档格式,我无法决定是mongo的做事方式。这两个例子是等价的吗?我们的想法是通过userId进行搜索并对userId进行索引。在我看来,任何一种模式的性能都是相同的。

多个书签作为集合中的单独文档:

{
  userId: 123,
  bookmarkName: "google",
  bookmarkUrl: "www.google.com"
},
{
  userId: 123,
  bookmarkName: "yahoo",
  bookmarkUrl: "www.yahoo.com"
},
{
  userId: 456,
  bookmarkName: "google",
  bookmarkUrl: "www.google.com"
}
每个用户在一个文档中

多个书签。

{
  userId: 123,
  bookmarks:[
    {
      bookmarkName: "google",
      bookmarkUrl: "www.google.com"
    },
    {
      bookmarkName: "yahoo",
      bookmarkUrl: "www.yahoo.com"
    }
  ]
},
{
  userId: 456,
  bookmarks:[
    {
      bookmarkName: "google",
      bookmarkUrl: "www.google.com"
    }
  ]
}

3 个答案:

答案 0 :(得分:1)

第二个选项的问题是它会导致文档不断增长。不断增长的文档对写入性能不利,因为数据库必须不断地在数据库文件周围移动它们。

为了提高写入性能,MongoDB始终将每个文档作为连续序列写入数据库文件,每个文档之间几乎没有填充。更改文档并且更改导致文档超出当前填充时,需要删除文档并将其移动到当前文件的末尾。这是一个非常缓慢的操作。

此外,MongoDB的每个文档的硬编码限制为16MB(主要是为了阻止不断增长的文档)。在您说明的用例中,这可能不是问题,但我认为这只是一个简化的示例,您的实际数据将为每个书签条目提供更多字段。当您为每个条目存储大量元数据时,16MB的限制可能会成为一个问题。

所以我建议你选择第一个选项。

答案 1 :(得分:0)

我会选择2 - 每个用户在一个文档中的多个书签,因为这个模式将利用MongoDB的丰富文档,也称为“非规范化”模型。

嵌入式数据模型允许应用程序在相同的数据库记录中存储相关的信息。因此,应用程序可能需要发出更少的查询和更新以完成常见操作。 Link

答案 2 :(得分:0)

  

有两种工具可以让应用程序代表这些   关系:引用和嵌入文档。

     

在设计数据模型时,请始终考虑应用程序的使用情况   数据(即查询,更新和数据处理)也是如此   作为数据本身的固有结构。

第二种结构代表Embedded type

一般情况下,当我们的应用需要时,应选择嵌入式结构:

a) better performance for read operations.
b) the ability to request and retrieve 
   related data in a single database operation. 
c) Data Consistency, to update related data in a single atomic write operation.
  

在MongoDB中,操作在文档级别是原子的。没有单身   写操作可以更改多个文档。操作   修改仍在操作的集合中的多个文档   一次一个文件。确保您的应用程序存储所有字段   在同一文档中具有原子依赖性要求。如果   应用程序可以容忍两个数据的非原子更新,   您可以将这些数据存储在单独的文档中。一个数据模型   将相关数据嵌入单个文档中可以促进这些类型   原子操作。

d) to issue fewer queries and updates to complete common operations.

何时不选择:

  

在文档中嵌入相关数据可能会导致出现这种情况   文件在创建后增长。文档增长会影响写入   性能并导致数据碎片化。 (限制为每人16MB   文件)

现在让我们从开发人员的角度比较结构:

我想要查看特定用户的所有书签:

第一种类型需要在所有文档上应用聚合。 获得汇总结果所需的最小函数集$match,$group(with $push operator)

db.collection.aggregate([{$match:{"userId":123}},{$group:{"_id":"$userId","bookmarkNames":{$push:"$bookmarkName"},"bookMarkUrls:{$push:"$bookmarkUrl"}"}}])

find(),它返回多个要迭代的文档。

嵌入式类型允许我们在查询查询中使用$ match获取它。

 db.collection.find({"userId":123});

这只是从开发人员的角度指出了额外的开销。我们将第一种类型视为嵌入文档的未展开形式。

第一种类型multiple bookmarks as separate documents in a collection, 通常用于记录日志。日志条目很大,并且有一个TTL,生存时间。在这种情况下,集合将是capped集合。文件将在特定时间段后自动删除。

底线,如果您的文档大小在任何特定时间都不会超过16 MB,请选择嵌入式类型。它也可以节省开发工作量。

另请参阅:MongoDB relationships: embed or reference?