即使仅投影索引后,MongoDB也不产生覆盖的查询

时间:2019-02-16 20:46:58

标签: mongodb mongodb-query

这是我正在使用的MongoDB驱动程序(Maven依赖项):

<dependencies>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongodb-driver-sync</artifactId>
        <version>3.10.1</version>
    </dependency>
</dependencies>

我为收藏集建立了两个索引:

    this.collection.createIndex(Indexes.ascending(
                "author",
                "created_utc",
                "subreddit"
            ));
    this.collection.createIndex(Indexes.ascending(
                "created_utc"
            ));

我跑了db.collection.getIndexes(),他们实际上在那里。

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "reddit.dump"
    },
    {
        "v" : 2,
        "key" : {
            "created_utc" : 1
        },
        "name" : "created_utc_1",
        "ns" : "reddit.dump"
    },
    {
        "v" : 2,
        "key" : {
            "author" : 1,
            "created_utc" : 1,
            "subreddit" : 1
        },
        "name" : "author_1_created_utc_1_subreddit_1",
        "ns" : "reddit.dump"
    }
]

然后我进行了以下查询:

    MongoCursor<Document> cursor = this.collection
            .find(and(
                      gte("created_utc", this.lowerBound),
                      lt("created_utc", this.upperBound)))
            .projection(fields(include("author", "created_utc", "subreddit"), 
                        exclude("_id"))).iterator();

this.lowerBoundthis.upperBound是整数,this.upperBound > this.lowerBound

由于某些未知原因,MongoDB似乎没有接受此作为覆盖查询。

当我直接在mongo上运行等效命令并要求解释时:

db.dump.find(
{created_utc: {$gt: 1543622399, $lt: 1543622401 }}, 
{author: 1, created_utc: 1, subreddit: 1, _id: 0})
.explain("executionStats")

我得到一个IXSCAN派生的FETCH,而totalDocsExamined不为零。因此,这不是涵盖的查询。这是解释的完整输出:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "reddit.dump",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [
                {
                    "created_utc" : {
                        "$lt" : 1543622401
                    }
                },
                {
                    "created_utc" : {
                        "$gt" : 1543622399
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "PROJECTION",
            "transformBy" : {
                "author" : 1,
                "created_utc" : 1,
                "subreddit" : 1,
                "_id" : 0
            },
            "inputStage" : {
                "stage" : "FETCH",
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "created_utc" : 1
                    },
                    "indexName" : "created_utc_1",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "created_utc" : [ ]
                    },
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "created_utc" : [
                            "(1543622399.0, 1543622401.0)"
                        ]
                    }
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 44,
        "executionTimeMillis" : 0,
        "totalKeysExamined" : 44,
        "totalDocsExamined" : 44,
        "executionStages" : {
            "stage" : "PROJECTION",
            "nReturned" : 44,
            "executionTimeMillisEstimate" : 0,
            "works" : 45,
            "advanced" : 44,
            "needTime" : 0,
            "needYield" : 0,
            "saveState" : 0,
            "restoreState" : 0,
            "isEOF" : 1,
            "invalidates" : 0,
            "transformBy" : {
                "author" : 1,
                "created_utc" : 1,
                "subreddit" : 1,
                "_id" : 0
            },
            "inputStage" : {
                "stage" : "FETCH",
                "nReturned" : 44,
                "executionTimeMillisEstimate" : 0,
                "works" : 45,
                "advanced" : 44,
                "needTime" : 0,
                "needYield" : 0,
                "saveState" : 0,
                "restoreState" : 0,
                "isEOF" : 1,
                "invalidates" : 0,
                "docsExamined" : 44,
                "alreadyHasObj" : 0,
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "nReturned" : 44,
                    "executionTimeMillisEstimate" : 0,
                    "works" : 45,
                    "advanced" : 44,
                    "needTime" : 0,
                    "needYield" : 0,
                    "saveState" : 0,
                    "restoreState" : 0,
                    "isEOF" : 1,
                    "invalidates" : 0,
                    "keyPattern" : {
                        "created_utc" : 1
                    },
                    "indexName" : "created_utc_1",
                    "isMultiKey" : false,
                    "multiKeyPaths" : {
                        "created_utc" : [ ]
                    },
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 2,
                    "direction" : "forward",
                    "indexBounds" : {
                        "created_utc" : [
                            "(1543622399.0, 1543622401.0)"
                        ]
                    },
                    "keysExamined" : 44,
                    "seeks" : 1,
                    "dupsTested" : 0,
                    "dupsDropped" : 0,
                    "seenInvalidated" : 0
                }
            }
        }
    },
    "serverInfo" : {
        "host" : "user-System-Product-Name",
        "port" : 27017,
        "version" : "3.6.3",
        "gitVersion" : "9586e557d54ef70f9ca4b43c26892cd55257e1a5"
    },
    "ok" : 1
}

如何进行覆盖式查询,以取得相同的结果?

这是我收藏夹中的文档的样子:

{
    "archived": false,
    "author": "HRNNNGH",
    "author_created_utc": 1533311589,
    "author_flair_background_color": null,
    "author_flair_css_class": null,
    "author_flair_richtext": [],
    "author_flair_template_id": null,
    "author_flair_text": null,
    "author_flair_text_color": null,
    "author_flair_type": "text",
    "author_fullname": "t2_1kcmg9n3",
    "author_patreon_flair": false,
    "body": "I LOVE THIS",
    "can_gild": true,
    "can_mod_post": false,
    "collapsed": false,
    "collapsed_reason": null,
    "controversiality": 0,
    "created_utc": 1543622400,
    "distinguished": null,
    "edited": false,
    "gilded": 0,
    "gildings": {
        "gid_1": 0,
        "gid_2": 0,
        "gid_3": 0
    },
    "id": "eatm38p",
    "is_submitter": false,
    "link_id": "t3_a1vhzf",
    "no_follow": false,
    "parent_id": "t3_a1vhzf",
    "permalink": "/r/ACPocketCamp/comments/a1vhzf/welcome_to_my_hair_salon/eatm38p/",
    "removal_reason": null,
    "retrieved_on": 1546258274,
    "score": 4,
    "send_replies": true,
    "stickied": false,
    "subreddit": "ACPocketCamp",
    "subreddit_id": "t5_3pg1s",
    "subreddit_name_prefixed": "r/ACPocketCamp",
    "subreddit_type": "public"
}

这是我想通过覆盖查询实现的目标:

{ "author" : "MyPhantomAccount", "created_utc" : 1543622400, "subreddit" : "ireland" }
{ "author" : "ardentArcane", "created_utc" : 1543622400, "subreddit" : "heroesofthestorm" }
{ "author" : "bbrownabbb", "created_utc" : 1543622400, "subreddit" : "nonononoyes" }
{ "author" : "DANKNESSLEVEL-69", "created_utc" : 1543622400, "subreddit" : "memes" }
{ "author" : "HRNNNGH", "created_utc" : 1543622400, "subreddit" : "ACPocketCamp" }
{ "author" : "DomIstKrieg", "created_utc" : 1543622400, "subreddit" : "AskReddit" }
{ "author" : "befooks", "created_utc" : 1543622400, "subreddit" : "northernlion" }
{ "author" : "meekosmom", "created_utc" : 1543622400, "subreddit" : "raisedbynarcissists" }
{ "author" : "[deleted]", "created_utc" : 1543622400, "subreddit" : "wallstreetbets" }
{ "author" : "Red580", "created_utc" : 1543622400, "subreddit" : "ForwardsFromKlandma" }
{ "author" : "rauland", "created_utc" : 1543622400, "subreddit" : "melbourne" }
{ "author" : "Mr-Morrison94", "created_utc" : 1543622400, "subreddit" : "FortNiteBR" }
{ "author" : "huskiesofinternets", "created_utc" : 1543622400, "subreddit" : "aww" }
{ "author" : "AnimaCorpusLucra", "created_utc" : 1543622400, "subreddit" : "wallstreetbets" }
{ "author" : "Shadow14l", "created_utc" : 1543622400, "subreddit" : "financialindependence" }
{ "author" : "potrap", "created_utc" : 1543622400, "subreddit" : "popheads" }
{ "author" : "FireandBloodandStuff", "created_utc" : 1543622400, "subreddit" : "dankmemes" }
{ "author" : "XChihiro", "created_utc" : 1543622400, "subreddit" : "AskReddit" }
{ "author" : "bjacks12", "created_utc" : 1543622400, "subreddit" : "latterdaysaints" }

2 个答案:

答案 0 :(得分:2)

据我所知,mongodb不会为该查询考虑您的3字段索引,因为它没有“作者”来减少索引搜索空间(即使您无论如何都是从所有作者那里获得的) )。即使给定hint使用3字段索引,它仍然不会产生覆盖查询(我无法告诉您原因)。

要获取涵盖的查询,您需要重新创建3字段索引,并首先列出created_utc

答案 1 :(得分:1)

如果您read carefully

  

涵盖的查询是可以完全使用   索引,而不必检查任何文档。索引涵盖   当以下两个条件同时适用时进行查询:

     
      
  • 查询中的所有字段都是索引的一部分,并且
  •   
  • 结果中返回的所有字段都在同一索引中。
  •   

它没有明确说明,但是仔细阅读它可以清楚地说明,它意味着一个满足查询和投影要求的单一索引。