Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-18830

Explain on near query with limit leaves out last search interval

    XMLWordPrintableJSON

Details

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Minor - P4 Minor - P4
    • 3.1.5
    • None
    • Geo
    • None
    • Fully Compatible
    • ALL
    • Hide

      To reproduce, first generate a geo collection. The following script will generate a uniform density dataset around (10,10)

      /* Modified from SERVER-18724: */
      // generate a grid map with geoJSON format
      function generateGridMapGeoJSON(collection, x1, y1, x2, y2, indexType) {
          var step_x = (x2 - x1) / 100.0;
          var step_y = (y2 - y1) / 100.0;
       
          collection.drop();
          collection.ensureIndex({loc: indexType}, {finestIndexedLevel:30, coarsestIndexedLevel:10});
       
          for( var i = x1; i < x2; ) {
              var bulk = collection.initializeUnorderedBulkOp();
       
              for(var j = y1; j < y2; ) {
                  bulk.insert({loc: {type: "Point", coordinates: [i, j]}});
                  j = j + step_y;
              }
              bulk.execute( {w: 1});
              i = i + step_x;
          }
          collection.getDB().getLastError();
      }
       
      // define the area for the map in collection
      var x_min = 9.995;
      var x_max =  10.005;
      var y_min = 9.995;
      var y_max =  10.005;
       
      // define the area to run query from
      // leave 1/7 out on each edge to make sure query are not run out of bound
      var x_query_min = x_min * (6.0/7.0);
      var x_query_max = x_max * (6.0/7.0);
      var y_query_min = y_min * (6.0/7.0);
      var y_query_max = y_max * (6.0/7.0);
       
      // query will run from a 13x13 grid
      var x_query_step = (x_query_max - x_query_min) / 13.0;
      var y_query_step = (y_query_max - y_query_min) / 13.0;
       
      var collection = db.getCollection("geo")
      generateGridMapGeoJSON(collection,  x_min, y_min, x_max, y_max, "2dsphere");
      

      Now, run the following query:

      db.geo.find({loc: { $near: {$geometry: {type: "Point", coordinates:  [ 10.000329670329670329, 10.0009890109890109888 ] } } } } ).limit(50).explain("executionStats")
      

      In the output, you will see the following (modified for readability):

      "inputStage" : {
      	"stage" : "GEO_NEAR_2DSPHERE",
      	(...)
      	"searchIntervals" : [
      		{
      			"minDistance" : 0,
      			"maxDistance" : 13.313786309945902,
      			"maxInclusive" : false
      		},
      		{
      			"minDistance" : 13.313786309945902,
      			"maxDistance" : 39.941358929837705,
      			"maxInclusive" : false
      		}
      	],
      	"inputStages" : [
      		{
      			(...)
      		},
      		{
      			(...)
      		},
      		{
      			(...)
      		}
      	]
      }
      

      The number of inputStages is 3, but the number of displayed searchIntervals is only 2. They should be equal.

      Show
      To reproduce, first generate a geo collection. The following script will generate a uniform density dataset around (10,10) /* Modified from SERVER-18724: */ // generate a grid map with geoJSON format function generateGridMapGeoJSON(collection, x1, y1, x2, y2, indexType) { var step_x = (x2 - x1) / 100.0; var step_y = (y2 - y1) / 100.0; collection.drop(); collection.ensureIndex({loc: indexType}, {finestIndexedLevel:30, coarsestIndexedLevel:10}); for ( var i = x1; i < x2; ) { var bulk = collection.initializeUnorderedBulkOp(); for ( var j = y1; j < y2; ) { bulk.insert({loc: {type: "Point" , coordinates: [i, j]}}); j = j + step_y; } bulk.execute( {w: 1}); i = i + step_x; } collection.getDB().getLastError(); } // define the area for the map in collection var x_min = 9.995; var x_max = 10.005; var y_min = 9.995; var y_max = 10.005;   // define the area to run query from // leave 1/7 out on each edge to make sure query are not run out of bound var x_query_min = x_min * (6.0/7.0); var x_query_max = x_max * (6.0/7.0); var y_query_min = y_min * (6.0/7.0); var y_query_max = y_max * (6.0/7.0); // query will run from a 13x13 grid var x_query_step = (x_query_max - x_query_min) / 13.0; var y_query_step = (y_query_max - y_query_min) / 13.0; var collection = db.getCollection( "geo" ) generateGridMapGeoJSON(collection, x_min, y_min, x_max, y_max, "2dsphere" ); Now, run the following query: db.geo.find({loc: { $near: {$geometry: {type: "Point" , coordinates: [ 10.000329670329670329, 10.0009890109890109888 ] } } } } ).limit(50).explain( "executionStats" ) In the output, you will see the following (modified for readability): "inputStage" : { "stage" : "GEO_NEAR_2DSPHERE" , (...) "searchIntervals" : [ { "minDistance" : 0, "maxDistance" : 13.313786309945902, "maxInclusive" : false }, { "minDistance" : 13.313786309945902, "maxDistance" : 39.941358929837705, "maxInclusive" : false } ], "inputStages" : [ { (...) }, { (...) }, { (...) } ] } The number of inputStages is 3, but the number of displayed searchIntervals is only 2. They should be equal.
    • RPL 5 06/26/16

    Description

      When performing an explain("executionStats") on a $near query, the searchIntervals field should contain all of the annuluses which are scanned. However, when a query is done with a limit, like the following:

      db.geo.find({loc: { $near: {$geometry: {type: "Point", coordinates:  [ 10.000329670329670329, 10.0009890109890109888 ] } } } } ).limit(50).explain("executionStats")
      

      The number of searchIntervals on the GEO_NEAR_2DSPHERE stage is one less than it should be. It should equal the number of inputStages.

      The reason this occurs is because in near.cpp, the method NearStage::advanceNext will only add to the intervalStats when the current buffer is finished. The limit will end early, before the buffer finishes. Therefore, the annulus will never be reported.

      Attachments

        Activity

          People

            brandon.zhang Brandon Zhang
            kevin.albertson@mongodb.com Kevin Albertson
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: