【问题标题】:mongodb $elemMatch does not use indexmongodb $elemMatch 不使用索引
【发布时间】:2015-12-02 19:11:52
【问题描述】:

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

"email":"dog@gmail.com"
"identities":[{"uid":"terrible","provider":"even_worse"}].

我在集合上创建了以下索引。基本上我有索引

1.“_id”上的索引:默认

2.关于“电子邮件”的索引:单独

3.关于“身份”的索引:单独

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()

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

这工作,使用索引,但我不明白为什么,我留下这个问题,希望有人可以解释工作。

【问题讨论】:

    标签: mongodb indices


    【解决方案1】:

    这是如何工作的:

    1. Mongodb 正在正确使用索引。
    2. 这完全取决于有多少文档与您的查询匹配

    按照我发布的示例,流程如下:

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

    如果我们对包含这两个文档的集合运行查询,将使用“电子邮件”索引,因为集合中的电子邮件可以将扫描的文档限制为仅一个。不会使用身份集合,也不会使用组合的“电子邮件”和“身份”索引。

    假设上述两个文档中,email 相同,但身份不同,则使用“identities”索引,同时忽略“email”索引和“identities”+“email”组合索引。

    现在假设我们添加了第三个文档:

    Document C: {"email":"tagger@gmail.com", "identities":[{"uid":"test","provider":"google"}]}
    

    此文档共享文档 A 的电子邮件,以及文档 B 的身份。 为了回答我的查询,MongoDb 将使用组合的“电子邮件”+“身份”索引,因为这两个索引字段在索引中都有多个文档,找到匹配项的唯一方法是缩小结果范围方式。

    您可以通过创建像我这样的集合,并像我一样在其上创建索引,最后生成上面的三个文档,并在每个查询上调用 explain() 来亲眼看到这一点。

    理查德·麦德森。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      • 2015-04-21
      • 2020-11-28
      • 1970-01-01
      • 1970-01-01
      • 2016-02-20
      • 1970-01-01
      相关资源
      最近更新 更多