summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorKevin Albertson <kevin.albertson@10gen.com>2015-06-29 12:22:34 -0400
committerKevin Albertson <kevin.albertson@10gen.com>2015-07-17 12:07:32 -0400
commitfa5851d3313e74086eb2c1340758e6b535decdf3 (patch)
treec6c647a2ba44763de79d8f55a8efe49457575570 /src/mongo/db
parentc33f68518b06e6b98596a8133d097e75d8431293 (diff)
downloadmongo-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.cpp27
-rw-r--r--src/mongo/db/geo/geometry_container.cpp4
-rw-r--r--src/mongo/db/geo/geometry_container.h5
-rw-r--r--src/mongo/db/index/expression_keys_private.cpp2
-rw-r--r--src/mongo/db/index/s2_indexing_params.cpp19
-rw-r--r--src/mongo/db/index/s2_indexing_params.h8
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(&regions);
}
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