diff options
author | Kevin Albertson <kevin.albertson@10gen.com> | 2015-06-29 12:22:34 -0400 |
---|---|---|
committer | Kevin Albertson <kevin.albertson@10gen.com> | 2015-07-17 12:07:32 -0400 |
commit | fa5851d3313e74086eb2c1340758e6b535decdf3 (patch) | |
tree | c6c647a2ba44763de79d8f55a8efe49457575570 /src/mongo/db | |
parent | c33f68518b06e6b98596a8133d097e75d8431293 (diff) | |
download | mongo-fa5851d3313e74086eb2c1340758e6b535decdf3.tar.gz |
SERVER-18921 Index points to finest level
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/exec/geo_near.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/geo/geometry_container.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/geo/geometry_container.h | 5 | ||||
-rw-r--r-- | src/mongo/db/index/expression_keys_private.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/index/s2_indexing_params.cpp | 19 | ||||
-rw-r--r-- | src/mongo/db/index/s2_indexing_params.h | 8 |
6 files changed, 51 insertions, 14 deletions
diff --git a/src/mongo/db/exec/geo_near.cpp b/src/mongo/db/exec/geo_near.cpp index cf1de9618e9..83f14aa887a 100644 --- a/src/mongo/db/exec/geo_near.cpp +++ b/src/mongo/db/exec/geo_near.cpp @@ -824,20 +824,33 @@ S2Region* buildS2Region(const R2Annulus& sphereBounds) { vector<S2Region*> regions; - S2Cap innerCap = S2Cap::FromAxisAngle( - latLng.ToPoint(), S1Angle::Radians(sphereBounds.getInner() / kRadiusOfEarthInMeters)); - innerCap = innerCap.Complement(); - regions.push_back(new S2Cap(innerCap)); + const double inner = sphereBounds.getInner(); + const double outer = sphereBounds.getOuter(); + + if (inner > 0) { + // TODO: Currently a workaround to fix occasional floating point errors + // in S2, where sometimes points near the axis will not be returned + // if inner == 0 + S2Cap innerCap = S2Cap::FromAxisAngle(latLng.ToPoint(), + S1Angle::Radians(inner / kRadiusOfEarthInMeters)); + innerCap = innerCap.Complement(); + regions.push_back(new S2Cap(innerCap)); + } // We only need to max bound if this is not a full search of the Earth // Using the constant here is important since we use the min of kMaxEarthDistance // and the actual bounds passed in to set up the search area. - if (sphereBounds.getOuter() < kMaxEarthDistanceInMeters) { - S2Cap outerCap = S2Cap::FromAxisAngle( - latLng.ToPoint(), S1Angle::Radians(sphereBounds.getOuter() / kRadiusOfEarthInMeters)); + if (outer < kMaxEarthDistanceInMeters) { + S2Cap outerCap = S2Cap::FromAxisAngle(latLng.ToPoint(), + S1Angle::Radians(outer / kRadiusOfEarthInMeters)); regions.push_back(new S2Cap(outerCap)); } + // if annulus is entire world, return a full cap + if (regions.empty()) { + regions.push_back(new S2Cap(S2Cap::Full())); + } + // Takes ownership of caps return new S2RegionIntersection(®ions); } diff --git a/src/mongo/db/geo/geometry_container.cpp b/src/mongo/db/geo/geometry_container.cpp index c74918e40c2..f3bfca36cfb 100644 --- a/src/mongo/db/geo/geometry_container.cpp +++ b/src/mongo/db/geo/geometry_container.cpp @@ -42,6 +42,10 @@ bool GeometryContainer::isSimpleContainer() const { return NULL != _point || NULL != _line || NULL != _polygon; } +bool GeometryContainer::isPoint() const { + return nullptr != _point; +} + bool GeometryContainer::supportsContains() const { return NULL != _polygon || NULL != _box || NULL != _cap || NULL != _multiPolygon || (NULL != _geometryCollection && (_geometryCollection->polygons.vector().size() > 0 || diff --git a/src/mongo/db/geo/geometry_container.h b/src/mongo/db/geo/geometry_container.h index 95dc8525440..0d7cea0e7c4 100644 --- a/src/mongo/db/geo/geometry_container.h +++ b/src/mongo/db/geo/geometry_container.h @@ -61,6 +61,11 @@ public: bool isSimpleContainer() const; /** + * Whether this geometry is a point + */ + bool isPoint() const; + + /** * Reports the CRS of the contained geometry. * TODO: Rework once we have collections of multiple CRSes */ diff --git a/src/mongo/db/index/expression_keys_private.cpp b/src/mongo/db/index/expression_keys_private.cpp index 7e549a8e2bc..82c4b8d5400 100644 --- a/src/mongo/db/index/expression_keys_private.cpp +++ b/src/mongo/db/index/expression_keys_private.cpp @@ -95,7 +95,7 @@ Status S2GetKeysForElement(const BSONElement& element, return status; S2RegionCoverer coverer; - params.configureCoverer(&coverer); + params.configureCoverer(geoContainer, &coverer); // Don't index big polygon if (geoContainer.getNativeCRS() == STRICT_SPHERE) { diff --git a/src/mongo/db/index/s2_indexing_params.cpp b/src/mongo/db/index/s2_indexing_params.cpp index 8217f16fa7e..a7579617564 100644 --- a/src/mongo/db/index/s2_indexing_params.cpp +++ b/src/mongo/db/index/s2_indexing_params.cpp @@ -30,8 +30,13 @@ #include "third_party/s2/s2regioncoverer.h" +#include "mongo/db/geo/geometry_container.h" + namespace mongo { +// Points will only be indexed at this level +const int kPointIndexedLevel = S2::kMaxCellLevel; + std::string S2IndexingParams::toString() const { std::stringstream ss; ss << "maxKeysPerInsert: " << maxKeysPerInsert << std::endl; @@ -42,9 +47,17 @@ std::string S2IndexingParams::toString() const { return ss.str(); } -void S2IndexingParams::configureCoverer(S2RegionCoverer* coverer) const { - coverer->set_min_level(coarsestIndexedLevel); - coverer->set_max_level(finestIndexedLevel); +void S2IndexingParams::configureCoverer(const GeometryContainer& geoContainer, + S2RegionCoverer* coverer) const { + // Points indexed to the finest level was introduced in version 3 + // For backwards compatibility, only do this if the version is > 2 + if (indexVersion >= S2_INDEX_VERSION_3 && geoContainer.isPoint()) { + coverer->set_min_level(kPointIndexedLevel); + coverer->set_max_level(kPointIndexedLevel); + } else { + coverer->set_min_level(coarsestIndexedLevel); + coverer->set_max_level(finestIndexedLevel); + } // This is advisory; the two above are strict. coverer->set_max_cells(maxCellsInCovering); diff --git a/src/mongo/db/index/s2_indexing_params.h b/src/mongo/db/index/s2_indexing_params.h index dc5123c1423..8c3e3a87323 100644 --- a/src/mongo/db/index/s2_indexing_params.h +++ b/src/mongo/db/index/s2_indexing_params.h @@ -34,6 +34,8 @@ class S2RegionCoverer; namespace mongo { +class GeometryContainer; + // An enum describing the version of an S2 index. enum S2IndexVersion { // The first version of the S2 index, introduced in MongoDB 2.4.0. Compatible with MongoDB @@ -57,9 +59,9 @@ struct S2IndexingParams { // This is really an advisory parameter that we pass to the cover generator. The // finest/coarsest index level determine the required # of cells. int maxCellsInCovering; - // What's the finest grained level that we'll index? + // What's the finest grained level that we'll index for non-points? int finestIndexedLevel; - // And, what's the coarsest? When we search in larger coverings + // And, what's the coarsest for non-points? When we search in larger coverings // we know we can stop here -- we index nothing coarser than this. int coarsestIndexedLevel; // Version of this index (specific to the index type). @@ -69,7 +71,7 @@ struct S2IndexingParams { std::string toString() const; - void configureCoverer(S2RegionCoverer* coverer) const; + void configureCoverer(const GeometryContainer& geoContainer, S2RegionCoverer* coverer) const; }; } // namespace mongo |