mongodb $ elemMatch不使用索引

时间:2015-12-02 19:11:53

标签: mongodb indices

我有一个包含两个字段的用户集合,结构如下。

"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})

这项工作,使用索引,但是我无法理解为什么,我将这个问题保持开放,希望有人可以解释这个问题。

1 个答案:

答案 0 :(得分:0)

以下是如何运作的:

  1. Mongodb正确使用索引。
  2. 这完全取决于与您的查询匹配的文档数量
  3. 按照我发布的示例,这里是流程如何:

    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。