索引嵌入文档的键到底意味着什么?
What does indexing a key of an embedded document really mean?
我仍然不明白索引嵌入文档的键是如何工作的。
假设我有以下博客集合 posts:
{
_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...
假设我现在在评论中为发件人 属性 设置索引:
db.blog.createIndex({'comments.sender':1})
现在的问题是:
这是否意味着无论它们在哪个数组中,都会为 sender 按升序排序的所有元素创建一个大索引?或者为每个数组创建一个索引?
为了更清楚:当我这样做时
blog.find({'comments.sender':'Jane Doe'}).toArray(function(err, array){})
它会遍历每个博客 post 并查找每个数组直到在该数组中找到一条记录并移动到下一个 post 中的下一个数组吗?或者有一个大索引,其中每条记录(按发送者排序)映射到该匹配项所在的原始数组?
这将创建一个索引,每个评论一个条目。如果你有 2 篇博文,每篇有 3 条评论,你将有一个包含 6 个条目的索引,由评论发件人姓名索引。您的第二个假设是正确的:您的搜索将使用此索引有效地找到所有发件人正确的评论,然后 return 相应的博客文章。
如此简短的回答:是的,这样做,它有效,您将获得最佳查询时间。
您可以使用 explain:
轻松检查查询的复杂性
> 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 个。删除索引,您将得到一个 table 扫描:
> 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
}
我仍然不明白索引嵌入文档的键是如何工作的。
假设我有以下博客集合 posts:
{
_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...
假设我现在在评论中为发件人 属性 设置索引:
db.blog.createIndex({'comments.sender':1})
现在的问题是:
这是否意味着无论它们在哪个数组中,都会为 sender 按升序排序的所有元素创建一个大索引?或者为每个数组创建一个索引?
为了更清楚:当我这样做时
blog.find({'comments.sender':'Jane Doe'}).toArray(function(err, array){})
它会遍历每个博客 post 并查找每个数组直到在该数组中找到一条记录并移动到下一个 post 中的下一个数组吗?或者有一个大索引,其中每条记录(按发送者排序)映射到该匹配项所在的原始数组?
这将创建一个索引,每个评论一个条目。如果你有 2 篇博文,每篇有 3 条评论,你将有一个包含 6 个条目的索引,由评论发件人姓名索引。您的第二个假设是正确的:您的搜索将使用此索引有效地找到所有发件人正确的评论,然后 return 相应的博客文章。
如此简短的回答:是的,这样做,它有效,您将获得最佳查询时间。
您可以使用 explain:
轻松检查查询的复杂性> 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 个。删除索引,您将得到一个 table 扫描:
> 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
}