diff options
author | Siyuan Zhou <visualzhou@gmail.com> | 2015-03-24 16:24:32 -0400 |
---|---|---|
committer | Ramon Fernandez <ramon.fernandez@mongodb.com> | 2015-03-27 10:37:11 -0400 |
commit | d9eee3757d06aa5467060438b4ff276d8439d737 (patch) | |
tree | 961e6a88caea97e282a863864262a7a1ab47048c | |
parent | 262e2a95fb8b880ff8f03d68774174da544d71d3 (diff) | |
download | mongo-d9eee3757d06aa5467060438b4ff276d8439d737.tar.gz |
SERVER-17469 Enable density estimator for 2d nearSphere.
(cherry picked from commit 3ee2c5c5c2c4ad0534138d567ccc7b053defff4a)
-rw-r--r-- | src/mongo/db/exec/geo_near.cpp | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/mongo/db/exec/geo_near.cpp b/src/mongo/db/exec/geo_near.cpp index a472a3bedaf..9c1b5b87d70 100644 --- a/src/mongo/db/exec/geo_near.cpp +++ b/src/mongo/db/exec/geo_near.cpp @@ -430,11 +430,6 @@ namespace mongo { WorkingSet* workingSet, Collection* collection) { - if (SPHERE == _nearParams.nearQuery->centroid->crs) { - _boundsIncrement = kMaxEarthDistanceInMeters / 1000.0; - return PlanStage::IS_EOF; - } - if (!_densityEstimator) { _densityEstimator.reset(new DensityEstimator(_twoDIndex, &_nearParams)); } @@ -443,8 +438,28 @@ namespace mongo { PlanStage::StageState state = _densityEstimator->work(txn, workingSet, collection, &estimatedDistance); if (state == PlanStage::IS_EOF) { + // 2d index only works with legacy points as centroid. $nearSphere will project + // the point into SPHERE CRS and calculate distance based on that. + // STRICT_SPHERE is impossible here, as GeoJSON centroid is not allowed for 2d index. + // Estimator finished its work, we need to finish initialization too. - _boundsIncrement = 3 * estimatedDistance; + if (SPHERE == _nearParams.nearQuery->centroid->crs) { + // Estimated distance is in degrees, convert it to meters. + _boundsIncrement = deg2rad(estimatedDistance) * kRadiusOfEarthInMeters * 3; + // Limit boundsIncrement to ~20KM, so that the first circle won't be too aggressive. + _boundsIncrement = std::min(_boundsIncrement, kMaxEarthDistanceInMeters / 1000.0); + } + else { + // We expand the radius by 3 times to give a reasonable starting search area. + // Assume points are distributed evenly. X is the edge size of cells at whose + // level we found a document in 4 neighbors. Thus the closest point is at least + // X/2 far from the centroid. The distance between two points is at least X. + // The area of Pi * (3X)^2 ~= 28 * X^2 will cover dozens of points at most. + // We'll explore the space with exponentially increasing radius if this guess is + // too small, so starting from a conservative initial radius doesn't hurt. + + _boundsIncrement = 3 * estimatedDistance; + } invariant(_boundsIncrement > 0.0); // Clean up |