Docs 菜单
Docs 主页
/
MongoDB Manual
/ /

避免无界数组

在此页面上

  • 例子
  • 子集模式
  • 参考数据
  • 使用 $lookup 联接数组字段
  • 了解详情

通过将数组存储为字段值,您可以嵌入数据并确保将一起访问的数据存储在一起。 但是,如果不限制大量中元素的数量,您的文档可能会超过 16 MB BSON文档大小限制。 无界大量可能会给应用程序资源造成压力,并降低索引性能。

无需嵌入整个数据集,而是使用子集设置和对绑定数组的引用,这可以提高性能并保持文档大小易于管理。 对数据进行子集化时,只需选择要处理的数据的必要部分,这样就可以只关注相关数据,从而减少内存使用量和处理时间。 引用数据时,您链接到外部数据源,而不是直接将其嵌入到文档中。 此方法可提高性能并减小文档大小。 通过使用子集设置和引用,可以绑定数组并更有效地管理日期。

考虑以下用于跟踪书店应用程序的书评的模式。 初始模式对 reviews字段使用一个大量。

{
title: "Harry Potter",
author: "J.K. Rowling",
publisher: "Scholastic",
reviews: [
{
user: "Alice",
review: "Great book!",
rating: 5
},
{
user: "Bob",
review: "Didn't like it!",
rating: 1
},
{
user: "Charlie",
review: "Not bad, but could be better.",
rating: 3
}
]
}

在此模式中, reviews字段是一个无界大量。 每次为这本书创建新查看时,应用程序都会向reviews大量添加一个新的子文档。 随着评论数量的增加,该大量可能会变得过大,导致应用程序资源紧张。

在此示例中,书店应用程序只需为每本书显示三个书评。 为避免使用无界数组,可以使用子集设计模式或文档引用,具体取决于您的使用案例。

当您需要快速访问权限不经常更新的数据时,对数据进行子集化是最好的选择。 使用 子集模式,您可以在图书文档中嵌入三条评论,以便在单个操作中返回所有必需的信息。 其他评论存储在单独的reviews集合中。 此模式设计模式具有以下优点:

  • 消除无界大量

  • 控制文档大小

  • 避免使用多个查询

books集合:

db.books.insertOne( [
{
title: "Harry Potter",
author: "J.K. Rowling",
publisher: "Scholastic",
reviews: [
{
reviewer: "Alice",
review: "Great book!",
rating: 5
},
{
reviewer: "Charlie",
review: "Didn't like it.",
rating: 1
},
{
reviewer: "Bob",
review: "Not bad, but could be better.",
rating: 3
}
],
}
] )

reviews集合:

db.reviews.insertMany( [
{
reviewer: "Jason",
review: "Did not enjoy!",
rating: 1
},
{
reviewer: "Pam",
review: "Favorite book!",
rating: 5
},
{
reviewer: "Bob",
review: "Not bad, but could be better.",
rating: 3
}
] )

这种方法会复制数据,导致更新成本高昂。 如果评价不经常更新,则此方法是最佳选择。

当您需要管理大型或频繁更新的数据集而不增加文档大小时,引用数据是最佳选择。

要引用数据,存储评论存储在单独的集合中,并向reviews集合中的文档添加review_id字段。 使用review_id字段引用books集合中的评论。

这种方法解决了无界大量的问题,但会引入延迟,因为您需要查询reviews集合以检索books集合的查看信息。 根据您的使用案例,这种额外的延迟可能是可以接受的,以避免无界数组引起的问题。

books集合:

db.books.insertMany( [
{
title: "Harry Potter",
author: "J.K. Rowling",
publisher: "Scholastic",
reviews: ["review1", "review2", "review3"]
},
{
title: "Pride and Prejudice",
author: "Jane Austen",
publisher: "Penguin",
reviews: ["review4", "review5"]
}
] )

reviews集合:

db.reviews.insertMany( [
{
review_id: "review1",
reviewer: "Jason",
review: "Did not enjoy!",
rating: 1
},
{
review_id: "review2",
reviewer: "Pam",
review: "Favorite book!",
rating: 5
},
{
review_id: "review3",
reviewer: "Bob",
review: "Not bad, but could be better.",
rating: 3
},
{
review_id: "review4",
reviewer: "Tina",
review: "Amazing!",
rating: 5
},
{
review_id: "review5",
reviewer: "Jacob",
review: "A little overrated",
rating: 4,
}
] )

如果您的booksreviews信息存储在单独的集合中,则应用程序需要执行$lookup操作来联接数据。

以下聚合操作连接上一示例中的booksreviews集合。

db.books.aggregate( [
{
$lookup: {
from: "reviews",
localField: "reviews",
foreignField: "review_id",
as: "reviewDetails"
}
}
] )

该操作返回以下内容:

[
{
_id: ObjectId('665de81eeda086b5e22dbcc9'),
title: 'Harry Potter',
author: 'J.K. Rowling',
publisher: 'Scholastic',
reviews: [ 'review1', 'review2', 'review3' ],
reviewDetails: [
{
_id: ObjectId('665de82beda086b5e22dbccb'),
review_id: 'review1',
reviewer: 'Jason',
review: 'Did not enjoy!',
rating: 1
},
{
_id: ObjectId('665de82beda086b5e22dbccc'),
review_id: 'review2',
reviewer: 'Pam',
review: 'Favorite book!',
rating: 5
},
{
_id: ObjectId('665de82beda086b5e22dbccd'),
review_id: 'review3',
reviewer: 'Bob',
review: 'Not bad, but could be better.',
rating: 3
} ]
},
{
_id: ObjectId('665de81eeda086b5e22dbcca'),
title: 'Pride and Prejudice',
author: 'Jane Austen',
publisher: 'Penguin',
reviews: [ 'review4', 'review5' ],
reviewDetails: [
{
_id: ObjectId('665de82beda086b5e22dbcce'),
review_id: 'review4',
reviewer: 'Tina',
review: 'Amazing!',
rating: 5
},
{
_id: ObjectId('665de82beda086b5e22dbccf'),
review_id: 'review5',
reviewer: 'Jacob',
review: 'A little overrated',
rating: 4
} ]
}
]

在此示例中, $lookup操作使用图书文档中的reviews大量和评论文档中的review_id字段将books集合与reviews集合连接起来。 reviewDetails文档存储组合后的数据。

后退

模式设计反模式