TEST(ExpressionGeoTest, GeoNear1) { BSONObj query = fromjson("{loc:{$near:{$maxDistance:100, " "$geometry:{type:\"Point\", coordinates:[0,0]}}}}"); NearQuery nq; ASSERT_OK(nq.parseFrom(query["loc"].Obj())); GeoNearMatchExpression gne; ASSERT(gne.init("a", nq, query).isOK()); // We can't match the data but we can make sure it was parsed OK. ASSERT_EQUALS(gne.getData().centroid.crs, SPHERE); ASSERT_EQUALS(gne.getData().minDistance, 0); ASSERT_EQUALS(gne.getData().maxDistance, 100); }
Status S2IndexCursor::seek(const BSONObj &position) { vector<GeoQuery> regions; bool isNearQuery = false; NearQuery nearQuery; // Go through the fields that we index, and for each geo one, make // a GeoQuery object for the S2*Cursor class to do intersection // testing/cover generating with. BSONObjIterator keyIt(_descriptor->keyPattern()); while (keyIt.more()) { BSONElement keyElt = keyIt.next(); if (keyElt.type() != String || IndexNames::GEO_2DSPHERE != keyElt.valuestr()) { continue; } BSONElement e = position.getFieldDotted(keyElt.fieldName()); if (e.eoo()) { continue; } if (!e.isABSONObj()) { continue; } BSONObj obj = e.Obj(); if (nearQuery.parseFrom(obj, _params.radius)) { if (isNearQuery) { return Status(ErrorCodes::BadValue, "Only one $near clause allowed: " + position.toString(), 16685); } isNearQuery = true; nearQuery.field = keyElt.fieldName(); continue; } GeoQuery geoQueryField(keyElt.fieldName()); if (!geoQueryField.parseFrom(obj)) { return Status(ErrorCodes::BadValue, "can't parse query (2dsphere): " + obj.toString(), 16535); } if (!geoQueryField.hasS2Region()) { return Status(ErrorCodes::BadValue, "Geometry unsupported: " + obj.toString(), 16684); } regions.push_back(geoQueryField); } // Remove all the indexed geo regions from the query. The s2*cursor will // instead create a covering for that key to speed up the search. // // One thing to note is that we create coverings for indexed geo keys during // a near search to speed it up further. BSONObjBuilder geoFieldsToNuke; if (isNearQuery) { geoFieldsToNuke.append(nearQuery.field, ""); } for (size_t i = 0; i < regions.size(); ++i) { geoFieldsToNuke.append(regions[i].getField(), ""); } // false means we want to filter OUT geoFieldsToNuke, not filter to include only that. BSONObj filteredQuery = position.filterFieldsUndotted(geoFieldsToNuke.obj(), false); if (isNearQuery) { S2NearIndexCursor* nearCursor = new S2NearIndexCursor(_descriptor, _params); _underlyingCursor.reset(nearCursor); nearCursor->seek(filteredQuery, nearQuery, regions); } else { S2SimpleCursor* simpleCursor = new S2SimpleCursor(_descriptor, _params); _underlyingCursor.reset(simpleCursor); simpleCursor->seek(filteredQuery, regions); } return Status::OK(); }