Docs 菜单
Docs 主页
/
MongoDB Atlas
/ /

避免无界数组

在此页面上

  • Overview
  • 例子
  • 了解详情

MongoDB 丰富的模式模型的优势之一是能够将数组存储为文档字段值。 通过将数组存储为字段值, 就可以在单个文档中建立一对多或多对多的关系模型, 而不是像在关系数据库中那样跨单独的集合建模。

但是,如果您不断向文档中的数组添加元素,则应小心谨慎。如果不限制数组中元素的数量,您的文档可能会增长到不可预测的大小。随着数组不断增长,对该数组读取和构建索引的性能逐渐下降。不断增长的大型数组会给应用程序资源造成压力,并使您的文档面临超过 BSON 文档大小限制的风险。

相反,请考虑为数组设限以提高性能,并将文档大小保持在可管理范围内。

考虑以下 publishers 集合的模式:

// publishers collection
{
"_id": "orielly",
"name": "O'Reilly Media",
"founded": 1980,
"location": "CA",
"books": [
{
"_id": 123456789,
"title": "MongoDB: The Definitive Guide",
"author": [ "Kristina Chodorow", "Mike Dirolf" ],
"published_date": ISODate("2010-09-24"),
"pages": 216,
"language": "English"
},
{
"_id": 234567890,
"title": "50 Tips and Tricks for MongoDB Developer",
"author": "Kristina Chodorow",
"published_date": ISODate("2011-05-06"),
"pages": 68,
"language": "English"
}
]
}

在此情况下,books 数组无界限。该出版公司每发行一本新书,便会向 books 数组添加一个新的子文档。随着出版公司不断发行图书,这些文档最终会变得很大,并对应用程序造成不成比例的内存压力。

为避免出现可变的无界数组,可将 publishers 集合分为两个集合,一个是 publishers 集合,另一个是 books 集合。与其在 publishers 文档中嵌入整个 book 文档,不如在图书文档中引用出版商:

// publishers collection
{
"_id": "oreilly",
"name": "O'Reilly Media",
"founded": 1980,
"location": "CA"
}
// books collection
{
"_id": 123456789,
"title": "MongoDB: The Definitive Guide",
"author": [ "Kristina Chodorow", "Mike Dirolf" ],
"published_date": ISODate("2010-09-24"),
"pages": 216,
"language": "English",
"publisher_id": "oreilly"
}
{
"_id": 234567890,
"title": "50 Tips and Tricks for MongoDB Developer",
"author": "Kristina Chodorow",
"published_date": ISODate("2011-05-06"),
"pages": 68,
"language": "English",
"publisher_id": "oreilly"
}

更新后的此模式会删除 publishers 集合中的无界限数组,并使用 publisher_id 字段在每个图书文档中放置对该出版商的引用。此操作可确保每个文档均有可管理的大小,且不存在文档字段变得过大的风险。

如果应用程序分别加载图书和出版商信息,则此方法尤其有效。如果应用程序需要同时使用书籍和信息,则需要执行 $lookup 操作来联结来自 publishersbooks 集合的数据。$lookup 操作的性能不是很高,但在这种情况下,为了避免使用无界数组,还是值得一试。

要了解如何将灵活数据模型整合到您的架构中,请参阅 MongoDB.live 2020 中的以下演示文稿:

后退

减少 $lookup