[SERVER-18830] Explain on near query with limit leaves out last search interval Created: 04/Jun/15  Updated: 05/Feb/16  Resolved: 17/Jun/15

Status: Closed
Project: Core Server
Component/s: Geo
Affects Version/s: None
Fix Version/s: 3.1.5

Type: Bug Priority: Minor - P4
Reporter: Kevin Albertson Assignee: Brandon Zhang
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible
Operating System: ALL
Steps To Reproduce:

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.

Sprint: RPL 5 06/26/16
Participants:

 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.



 Comments   
Comment by Githook User [ 17/Jun/15 ]

Author:

{u'name': u'Brandon Zhang', u'email': u'brandonzhang@Brandons-MacBook-Pro-2.local'}

Message: SERVER-18830 Fixed explain output for geoNear

Closes #987

Signed-off-by: Siyuan Zhou <siyuan.zhou@mongodb.com>
Branch: master
https://github.com/mongodb/mongo/commit/438c694cbd3ee368430ba7b95b9be6765217f514

Generated at Thu Feb 08 03:48:52 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.