Mongodb – How to interpret this “db.explain()” for this mongodb query

indexmongodb

db.tablebusiness.find({ "LongitudeLatitude" : { "$within" : { "$centerSphere" : [[106.772835, -6.186753], 0.0089967464101566] } }, "indexContents" : { "$all" : ["warung"] }, "Prominent" : { "$gte" : 15 } }).limit(50).explain;


{
        "cursor" : "GeoBrowse-circle",
        "nscanned" : 50,
        "nscannedObjects" : 50,
        "n" : 50,
        "millis" : 214,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {
                "LongitudeLatitude" : [ ]
        },
        "keysChecked" : NumberLong(13215),
        "lookedAt" : NumberLong(13215),
        "matchesPerfd" : NumberLong(13215),
        "objectsLoaded" : NumberLong(6674),
        "pointsLoaded" : NumberLong(0)
}

The query search for businesses within a circle that contains certain character. Typical data looks like this

/* 4 */
{
  "_id" : "made's-warung__-6.18_106.78",
  "BuildingID" : null,
  "Title" : "Made’s Warung",
  "InBuildingAddress" : null,
  "Building" : null,
  "Street" : "Seminyak-Kuta",
  "Districts" : [],
  "City" : "Bali",
  "Country" : "Indonesia",
  "DistanceFromGoogleAddress" : 0.0,
  "Checkin" : 0,
  "Note" : null,
  "PeopleCount" : 106,
  "Prominent" : 106.0,
  "CountViews" : 0,
  "StreetAdditional" : null,
  "LongitudeLatitude" : {
    "Longitude" : 106.783746,
    "Latitude" : -6.177905
  },
  "Rating" : {
    "Stars" : 0.0,
    "Weight" : 0.0
  },
  "CurrentlyWorkedURL" : null,
  "Reviews" : [],
  "ZIP" : null,
  "Tags" : ["Asian Restaurant"],
  "Phones" : [],
  "Website" : null,
  "Email" : null,
  "Price" : null,
  "openingHour" : null,
  "Promotions" : [],
  "SomethingWrong" : false,
  "BizMenus" : [],
  "Brochures" : [],
  "Aliases" : [],
  "indexContents" : ["asian", "sian", "ian", "an", "n", "restaura", "estauran", "staurant", "taurant", "aurant", "urant", "rant", "ant", "nt", "t", "made’s", "ade’s", "de’s", "e’s", "’s", "s", "warung", "arung", "rung", "ung", "ng", "g"]
}

Also look at this one:

db.tablebusiness.find({ "LongitudeLatitude" : { "$nearSphere" : [106.772835, -6.186753], "$maxDistance" : 0.044983732050783008 }, "Prominent" : { "$gte" : 15 }, "indexContents" : { "$all" : [/^aru/, /^asi/] } }).limit(50).explain();

{
        "cursor" : "GeoSearchCursor",
        "nscanned" : 50,
        "nscannedObjects" : 50,
        "n" : 50,
        "millis" : 2977,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {

        }
}
>

What does it mean? Is indexes used? Which one?

Best Answer

Yes, an index is used in both cases, just with different operators. The key to determining whether a query has used an index or not is the "cursor" : field. If this says BasicCursor then no index was used (a table scan was performed). Otherwise an index was used.

In your case you are using a "2d" geo index each time, in fact for $nearsphere and $within, $centersphere to work, you must be using a geo index.

As for the rest of the output, they are both returning 50 objects, the first is significantly faster. You can see the explanation of the various fields here:

http://www.mongodb.org/display/DOCS/Explain

You have not listed what indexes you have defined, but if you wanted to attempt to speed things up you can try adding a compound index. Remember a query in MongoDB can only use one index at a time and for the geo commands to work that must be a 2d/geo index, so if you have indexes on your other fields, they will not be used unless they are part of a compound index with your geo index. You should also note that the 2d index must currently be the first field in the compound index, per here:

http://www.mongodb.org/display/DOCS/Geospatial+Indexing#GeospatialIndexing-CompoundIndexes