summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/geo_near.cpp
diff options
context:
space:
mode:
authorSiyuan Zhou <visualzhou@gmail.com>2015-03-24 16:24:32 -0400
committerSiyuan Zhou <visualzhou@gmail.com>2015-03-25 17:18:28 -0400
commit3ee2c5c5c2c4ad0534138d567ccc7b053defff4a (patch)
tree76679ff70aceb4ed1be79686593918793ebba488 /src/mongo/db/exec/geo_near.cpp
parentd5cd0b603f5f60f7e63523fac31a2a00aa0114f8 (diff)
downloadmongo-3ee2c5c5c2c4ad0534138d567ccc7b053defff4a.tar.gz
SERVER-17469 Enable density estimator for 2d nearSphere.
Diffstat (limited to 'src/mongo/db/exec/geo_near.cpp')
-rw-r--r--src/mongo/db/exec/geo_near.cpp27
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 9026afc7239..96441e492a8 100644
--- a/src/mongo/db/exec/geo_near.cpp
+++ b/src/mongo/db/exec/geo_near.cpp
@@ -433,11 +433,6 @@ namespace mongo {
Collection* collection,
WorkingSetID* out)
{
- if (SPHERE == _nearParams.nearQuery->centroid->crs) {
- _boundsIncrement = kMaxEarthDistanceInMeters / 1000.0;
- return PlanStage::IS_EOF;
- }
-
if (!_densityEstimator) {
_densityEstimator.reset(new DensityEstimator(_twoDIndex, &_nearParams));
}
@@ -447,8 +442,28 @@ namespace mongo {
&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