summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiyuan Zhou <visualzhou@gmail.com>2015-03-24 16:24:32 -0400
committerRamon Fernandez <ramon.fernandez@mongodb.com>2015-03-27 10:37:11 -0400
commitd9eee3757d06aa5467060438b4ff276d8439d737 (patch)
tree961e6a88caea97e282a863864262a7a1ab47048c
parent262e2a95fb8b880ff8f03d68774174da544d71d3 (diff)
downloadmongo-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.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 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