索引嵌入文档的键真正意味着什么?

时间:2015-05-06 09:21:30

标签: arrays node.js mongodb indexing embedded-documents

我仍然无法理解嵌入式文档的密钥索引是如何工作的 假设我有以下博客文章集:

{
    _id:0,
    author: 'John Doe',
    content: 'How indexing an embedded document work?',
    comments:
    [
      {
        sender:'Jane Doe',
        content: 'I can\'t make it out either.'
      },
      etc...
    ]
},
etc...

假设我现在在评论中的sender属性上设置索引:

db.blog.createIndex({'comments.sender':1})

现在的问题是:
这是否意味着为发件人按升序排序的所有元素创建一个大索引,无论它们在哪个数组中?或者为每个数组创建索引?
为了更清楚:当我做

blog.find({'comments.sender':'Jane Doe'}).toArray(function(err, array){})

是否会查看每篇博文并查找每个数组,直到在该数组中找到记录并转到下一篇文章中的下一个数组?或者有一个大索引,其中每个记录(按发件人排序)映射到此匹配所在的原始数组?

1 个答案:

答案 0 :(得分:1)

这会创建一个索引,每个注释都有一个条目。如果您有2篇博客文章,每篇博文都有3条评论,那么您将拥有一个包含6个条目的索引,并以评论发件人姓名为索引。您的第二个假设是正确的:您的搜索将使用此索引有效地找到正确发件人的所有评论,然后返回相应的博客帖子。

如此简短的回答:是的,这样做,它可以工作,你将获得最佳的查询时间。

您可以通过解释轻松检查查询的复杂性:

> db.blog.insert({'comments': [{'sender': 'Jane'}]})
WriteResult({ "nInserted" : 1 })
> db.blog.insert({'comments': [{'sender': 'Jane'}, {'sender': 'Joe'}]})
WriteResult({ "nInserted" : 1 })
> db.blog.insert({'comments': [{'sender': 'Joe'}]})
WriteResult({ "nInserted" : 1 })
> db.blog.ensureIndex({'comments.sender': 1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.blog.find({'comments.sender': 'Jane'}).count()
2
> db.blog.find({'comments.sender': 'Jane'}).explain()
{
        "cursor" : "BtreeCursor comments.sender_1",
        "isMultiKey" : true,
        "n" : 2,
        "nscannedObjects" : 2,
        "nscanned" : 2,
        "nscannedObjectsAllPlans" : 2,
        "nscannedAllPlans" : 2,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "comments.sender" : [
                        [
                                "Jane",
                                "Jane"
                        ]
                ]
        },
        "server" : "metrics.9.0.api.production.infinit.io:27017",
        "filterSet" : false
}

我们在这里看到确实使用了索引(" BtreeCursor")并且只扫描了2个对象,而不是全部3.删除索引并进行表扫描:

> db.blog.dropIndex({'comments.sender': 1})
{ "nIndexesWas" : 2, "ok" : 1 }
> db.blog.find({'comments.sender': 'Jane'}).explain()
{
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 2,
        "nscannedObjects" : 3,
        "nscanned" : 3,
        "nscannedObjectsAllPlans" : 3,
        "nscannedAllPlans" : 3,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "server" : "metrics.9.0.api.production.infinit.io:27017",
        "filterSet" : false
}