summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/geo_s2descindex.js65
-rw-r--r--jstests/geo_s2validindex.js23
-rw-r--r--src/mongo/db/index/s2_access_method.cpp9
-rw-r--r--src/mongo/db/index/s2_near_cursor.cpp8
-rw-r--r--src/mongo/db/index/s2_simple_cursor.cpp8
5 files changed, 110 insertions, 3 deletions
diff --git a/jstests/geo_s2descindex.js b/jstests/geo_s2descindex.js
new file mode 100644
index 00000000000..215533392a0
--- /dev/null
+++ b/jstests/geo_s2descindex.js
@@ -0,0 +1,65 @@
+//
+// Tests 2dsphere with descending fields, ensures correct lookup
+//
+
+var coll = db.getCollection("twodspheredesc");
+
+var descriptors = [["field1", -1], ["field2", -1], ["coordinates", "2dsphere"]]
+var docA = {field1 : "a", field2 : 1, coordinates : [-118.2400013, 34.073893]}
+var docB = {field1 : "b", field2 : 1, coordinates : [-118.2400012, 34.073894]}
+
+// Try both regular and near index cursors
+var query = {coordinates : {$geoWithin : {$centerSphere : [[-118.240013, 34.073893],
+ 0.44915760491198753]}}};
+var queryNear = {coordinates : {$geoNear : {"type" : "Point", "coordinates" : [0, 0]}}};
+
+//
+// The idea here is we try "2dsphere" indexes in combination with descending
+// other fields in various
+// positions and ensure that we return correct results.
+//
+
+for ( var t = 0; t < descriptors.length; t++) {
+
+ var descriptor = {};
+ for ( var i = 0; i < descriptors.length; i++) {
+ descriptor[descriptors[i][0]] = descriptors[i][1];
+ }
+
+ jsTest.log("Trying 2dsphere index with descriptor " + tojson(descriptor));
+
+ coll.drop();
+ coll.ensureIndex(descriptor);
+
+ coll.insert(docA);
+ coll.insert(docB);
+
+ assert.eq(1, coll.count(Object.merge(query, {field1 : "a"})));
+ assert.eq(1, coll.count(Object.merge(query, {field1 : "b"})));
+ assert.eq(2, coll.count(Object.merge(query, {field2 : 1})));
+ assert.eq(0, coll.count(Object.merge(query, {field2 : 0})));
+ assert.eq(2, coll.count(queryNear));
+
+ var firstEls = descriptors.splice(1);
+ descriptors = firstEls.concat(descriptors);
+}
+
+//
+// Data taken from previously-hanging result
+//
+
+jsTest.log("Trying case found in wild...");
+
+coll.drop();
+coll.ensureIndex({coordinates : "2dsphere", field : -1});
+coll.insert({coordinates : [-118.240013, 34.073893]});
+var query = {coordinates : {$geoWithin : {$centerSphere : [[-118.240013, 34.073893],
+ 0.44915760491198753]}},
+ field : 1};
+
+assert.eq(null, coll.findOne(query));
+coll.remove({})
+coll.insert({coordinates : [-118.240013, 34.073893], field : 1});
+assert.neq(null, coll.findOne(query));
+
+jsTest.log("Success!");
diff --git a/jstests/geo_s2validindex.js b/jstests/geo_s2validindex.js
new file mode 100644
index 00000000000..af62119ad69
--- /dev/null
+++ b/jstests/geo_s2validindex.js
@@ -0,0 +1,23 @@
+//
+// Tests valid cases for creation of 2dsphere index
+//
+
+var coll = db.getCollection("twodspherevalid");
+
+// Valid index
+coll.drop();
+assert.eq(undefined, coll.ensureIndex({geo : "2dsphere", other : 1}));
+
+// Valid index
+coll.drop();
+assert.eq(undefined, coll.ensureIndex({geo : "2dsphere", other : 1, geo2 : "2dsphere"}));
+
+// Invalid index, using hash with 2dsphere
+coll.drop();
+assert.neq(undefined, coll.ensureIndex({geo : "2dsphere", other : "hash"}).err);
+
+// Invalid index, using 2d with 2dsphere
+coll.drop();
+assert.neq(undefined, coll.ensureIndex({geo : "2dsphere", other : "2d"}).err);
+
+jsTest.log("Success!");
diff --git a/src/mongo/db/index/s2_access_method.cpp b/src/mongo/db/index/s2_access_method.cpp
index ca4fc60d2c8..c43ecc75964 100644
--- a/src/mongo/db/index/s2_access_method.cpp
+++ b/src/mongo/db/index/s2_access_method.cpp
@@ -73,13 +73,20 @@ namespace mongo {
_params.finestIndexedLevel >= _params.coarsestIndexedLevel);
int geoFields = 0;
+
// Categorize the fields we're indexing and make sure we have a geo field.
BSONObjIterator i(descriptor->keyPattern());
while (i.more()) {
BSONElement e = i.next();
- if (e.type() == String && IndexNames::GEO_2DSPHERE == e.valuestr()) {
+ if (e.type() == String && IndexNames::GEO_2DSPHERE == e.String() ) {
++geoFields;
}
+ else {
+ // We check for numeric in 2d, so that's the check here
+ uassert( 16823, (string)"Cannot use " + IndexNames::GEO_2DSPHERE +
+ " index with other special index types: " + e.toString(),
+ e.isNumber() );
+ }
}
uassert(16750, "Expect at least one geo field, spec=" + descriptor->keyPattern().toString(),
geoFields >= 1);
diff --git a/src/mongo/db/index/s2_near_cursor.cpp b/src/mongo/db/index/s2_near_cursor.cpp
index 780735e4b37..51bc07b75b2 100644
--- a/src/mongo/db/index/s2_near_cursor.cpp
+++ b/src/mongo/db/index/s2_near_cursor.cpp
@@ -51,7 +51,13 @@ namespace mongo {
BSONObjIterator specIt(_descriptor->keyPattern());
while (specIt.more()) {
BSONElement e = specIt.next();
- specBuilder.append(e.fieldName(), 1);
+ // Checked in AccessMethod already, so we know this spec has only numbers and 2dsphere
+ if ( e.type() == String ) {
+ specBuilder.append( e.fieldName(), 1 );
+ }
+ else {
+ specBuilder.append( e.fieldName(), e.numberInt() );
+ }
}
_specForFRV = specBuilder.obj();
diff --git a/src/mongo/db/index/s2_simple_cursor.cpp b/src/mongo/db/index/s2_simple_cursor.cpp
index 25c88aa8f3f..3b3e988a908 100644
--- a/src/mongo/db/index/s2_simple_cursor.cpp
+++ b/src/mongo/db/index/s2_simple_cursor.cpp
@@ -46,7 +46,13 @@ namespace mongo {
BSONObjIterator i(_descriptor->keyPattern());
while (i.more()) {
BSONElement e = i.next();
- specBuilder.append(e.fieldName(), 1);
+ // Checked in AccessMethod already, so we know this spec has only numbers and 2dsphere
+ if ( e.type() == String ) {
+ specBuilder.append( e.fieldName(), 1 );
+ }
+ else {
+ specBuilder.append( e.fieldName(), e.numberInt() );
+ }
}
BSONObj spec = specBuilder.obj();