我有一个包含两个字段的用户集合,结构如下。
"email":"dog@gmail.com"
"identities":[{"uid":"terrible","provider":"even_worse"}].
我在集合上创建了以下索引。基本上我有指数
1." _id"的索引:默认
2."电子邮件"的索引:独自一人
3."身份和#34;的索引:独自一人
4." _id"的索引+"身份"
5."电子邮件"的索引+"身份"
rs0:PRIMARY> db.users.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test_development.users"
},
{
"v" : 1,
"key" : {
"email" : 1
},
"name" : "email_index",
"ns" : "test_development.users"
},
{
"v" : 1,
"key" : {
"identities.uid" : 1,
"identities.provider" : 1
},
"name" : "identities_index",
"ns" : "test_development.users"
},
{
"v" : 1,
"key" : {
"_id" : 1,
"identities.uid" : 1,
"identities.provider" : 1
},
"name" : "id_and_identities_index",
"ns" : "test_development.users"
},
{
"v" : 1,
"key" : {
"email" : 1,
"identities.uid" : 1,
"identities.provider" : 1
},
"name" : "email_and_identities_index",
"ns" : "test_development.users"
}
]
我打开explain()时执行以下查询:
db.users.find({ "email":"test@gmai.com","identities":{$elemMatch : {"uid":"cat", "provider": "dog"}}}).explain()
解释结果表明只使用了电子邮件索引,并且从不查询身份索引。我不知道如何解决这个问题。 任何帮助表示赞赏。
{
"cursor" : "BtreeCursor email_index",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"nscannedObjectsAllPlans" : 0,
"nscannedAllPlans" : 0,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"email" : [
[
"test@gmai.com",
"test@gmai.com"
]
]
},
"server" : "dragon:27017",
"filterSet" : false
}
我觉得我不需要这么多索引,但我阅读了文档和前缀索引部分,所以我创建了所有这些索引。对于我的程序中的其他一些查询,我需要索引2,3,4,我希望索引5可以解决这个特定的查询。但它不起作用。
此致 理查德·马德森
更新:使用示意工作
db.users.find({ "email":"test@gmai.com","identities":{$elemMatch : {"uid":"cat", "provider": "dog"}}}).hint({"email":1, "identities.uid":1, "identities.provider":1})
这项工作,使用索引,但是我无法理解为什么,我将这个问题保持开放,希望有人可以解释这个问题。
答案 0 :(得分:0)
以下是如何运作的:
按照我发布的示例,这里是流程如何:
a。如果搜索的两个字段在索引中都有多个doc id,则将使用组合索引。 这意味着:
Document A: {"email":"tagger@gmail.com","identities":[{"uid":"test","provider":"facebook"}]}
Document B: {"email":"raggy@gmail.com","identities":[{"uid":"test","provider":"google"}]}
如果我们使用这两个文档对集合运行查询,那么"电子邮件"将使用索引,因为集合中的电子邮件可以将扫描的文档限制为仅一个。不会使用身份集合,也不会使用组合的电子邮件"和#34;身份"索引。
假设在上述两个文件中,电子邮件是相同的,但身份不同,那么"身份"将使用索引,忽略"电子邮件"索引和组合的身份" +"电子邮件"索引。
现在假设我们在争论中添加第三个文档:
Document C: {"email":"tagger@gmail.com", "identities":[{"uid":"test","provider":"google"}]}
本文件分享了文件A的电子邮件和文件B的身份。 为了回答我的问题,MongoDb将使用组合的"电子邮件" +"身份" index,因为两个索引字段在索引中都有多个文档,找到匹配的唯一方法是缩小两种方式的结果。
你可以通过像我一样创建一个集合,并像我一样创建索引,最后生成上面的三个文档,并在每个查询上调用explain()来为自己看到这一点。
Richard Madson。