了解 mongodb 索引:索引经常查询的链接文档

Understanding mongodb indexing: Indexing linked document that is frequently queried

这是我的应用进行的查询类型的一个简单示例

所以你有一个记事本和笔记集。笔记文档使用 notepadId 链接到记事本文档。

所以典型的查询如下所示:

Notes.find({notepadId: notepad._id})

用户每个记事本可以有数百条笔记。他们经常在记事本之间切换。用户还可以在记事本上进行协作。

我还有一种机制可以在页面加载时计算服务器上记事本中的所有笔记。这是因为我需要知道在使用分页后要显示多少页。

Notes.find({notepadId: notepad._id}).count()

我对 MongoDB 索引不是很熟悉,尝试搜索 'Indexing linked documents' 但找不到任何关于索引链接文档的信息。

这是索引链接文档字段的常见做法吗?

所以在这种情况下,我想在 Notes 集合的字段 notepadId

上设置一个索引

好主意,坏主意,为什么?

文档变成"linked"只在应用层。 mongodb 本身的 notepadId 字段没有什么特别之处。通过此字段进行索引将使计数非常有效,因为它是 covered query,不需要磁盘 IO。

那些讨论(索引覆盖查询)的答案,忘了告诉你,要获得完全索引覆盖的结果,你必须做排除 _id 字段的投影。

让我解释一下。

在全索引覆盖查询中,我们只读取索引而不是磁盘中的任何其他内容。如果我们有 f.ex。 Notes.createIndex({notepadId: 1, archived: 1}) (涵盖了这两个查询),我们在那里做 Notes.find({notepadId: notepad._id}).count()将是两个不同的动作。首先是 "find" 收集结果集,然后 "count" 计算结果集中有多少文档。

查找总是包括(在它的结果集中)“_id”字段,如果它没有被排除在投影中的话。因为我们的索引没有 _id 字段,只有指向文档磁盘位置的指针,所以 find 首先使用索引找到所需的文档,然后跳转到该索引入口指向的磁盘位置,读取文档的 _id。不是我们想要的。为了防止这种情况,我们需要投影。于是查询:

Notes.find({notepadId: notepad._id},{"_id":0, "notepadId":1}).count()

将 return(在查找部分)仅列出 "notepadId",而不是其他任何内容。

另一个查询是:Notes.find({notepadId: notepad._id, archived: false},{"_id":0, "notepadId":1, archived:1}).count()

您可以通过两个不同的查询轻松测试它:

Notes.find({notepadId: notepad._id}).explain()
Notes.find({notepadId: notepad._id},{"_id":0, "notepadId":1}).explain()

并比较结果。