Monta
Monta

Reputation: 1180

Mongodb Compound index and sorting

I have this collection :

db.place.find() : 
    {
    _id : "p1",
    alterNames : ["abcd","abcD"],
    population : 122
    }
    {
    _id : "p2",
    alterNames : ["qsdf","qsDF"],
    population : 100
    }

I want to find documents having alterNames starting with "ab" and sort them by population. I created this index : {alterNames : 1, population : -1}

My query :

db.place.find({alterNames : /^ab/}).sort({population : -1}).limit(10).explain()

I was waiting to see "n" = "nScannedObjects" = 10 What I got :

"n" = 10
"nScannedObjects" = 4765

Did I miss a thing?

Edit : Here is the full explain :

db.place.find({alterNames : /^pari/ }).sort({population : -1}).limit(10).explain()

      "clauses" : [
              {
                      "cursor" : "BtreeCursor alterNames_1_population_-1",
                      "isMultiKey" : true,
                      "n" : 10,
                      "nscannedObjects" : 4765,
                      "nscanned" : 4883,
                      "scanAndOrder" : true,
                      "indexOnly" : false,
                      "nChunkSkips" : 0,
                      "indexBounds" : {
                              "alterNames" : [
                                      [
                                              "pari",
                                              "parj"
                                      ],
                                      [
                                              /^pari/,
                                              /^pari/
                                      ]
                              ],
                              "population" : [
                                      [
                                              {
                                                      "$maxElement" : 1
                                              },
                                              {
                                                      "$minElement" : 1
                                              }
                                      ]
                              ]
                      }
              },
              {
                      "cursor" : "BtreeCursor ",
                      "isMultiKey" : false,
                      "n" : 0,
                      "nscannedObjects" : 0,
                      "nscanned" : 0,
                      "scanAndOrder" : true,
                      "indexOnly" : false,
                      "nChunkSkips" : 0,
                      "indexBounds" : {
                              "alterNames" : [
                                      [
                                              "pari",
                                              "parj"
                                      ],
                                      [
                                              /^pari/,
                                              /^pari/
                                      ]
                              ],
                              "population" : [
                                      [
                                              {
                                                      "$maxElement" : 1
                                              },
                                              {
                                                      "$minElement" : 1
                                              }
                                      ]
                              ]
                      }
              }
      ],
      "cursor" : "QueryOptimizerCursor",
      "n" : 10,
      "nscannedObjects" : 4765,
      "nscanned" : 4883,
      "nscannedObjectsAllPlans" : 4765,
      "nscannedAllPlans" : 4883,
      "scanAndOrder" : false,
      "nYields" : 890,
      "nChunkSkips" : 0,
      "millis" : 396,
      "server" : "localhost:27017",
      "filterSet" : false

Upvotes: 0

Views: 55

Answers (1)

wdberkeley
wdberkeley

Reputation: 11671

Your notation is confusing. I'm assuming your collection consists of documents that look like the two documents in the places array.

> db.test.find()
{ "_id" : "p1", "alterNames" : [ "abcd", "abcD" ], "population" : 122 }
{ "_id" : "p2", "alterNames" : [ "qsdf", "qsDF" ], "population" : 100 }

For a left-anchored regex like /^ab/, MongoDB converts the query to one that's actually a range query and can efficiently use the index

{ "alterNames" : /^ab/ } => { "alterNames" : { "$gte" : "ab", "$lt" : "ac" } }

Each value that matches the range, for example "abcd", has an index of population values below it for documents with an alterNames (multikey) value of "abcd". To return the matching documents in population-order, MongoDB has to externally sort the documents returned from each matching bucket. I believe that's the source of your higher nscannedObjects. If you check the explain (which would have been nice to include in its entirety), you should find scanAndOrder : true.

Upvotes: 1

Related Questions