BSONObj S2NearCursor::makeFRSObject() { BSONObjBuilder frsObjBuilder; frsObjBuilder.appendElements(_filteredQuery); S2RegionCoverer coverer; _params.configureCoverer(&coverer); // Step 1: Make the monstrous BSONObj that describes what keys we want. for (size_t i = 0; i < _fields.size(); ++i) { const GeoQueryField &field = _fields[i]; S2Point center = field.getCentroid(); BSONObj inExpr; // Caps are inclusive and inverting a cap includes the border. This means that our // initial _innerRadius of 0 is OK -- we'll still find a point that is exactly at // the start of our search. S2Cap innerCap = S2Cap::FromAxisAngle(center, S1Angle::Radians(_innerRadius / _params.radius)); S2Cap invInnerCap = innerCap.Complement(); S2Cap outerCap = S2Cap::FromAxisAngle(center, S1Angle::Radians(_outerRadius / _params.radius)); vector<S2Region*> regions; regions.push_back(&invInnerCap); regions.push_back(&outerCap); S2RegionIntersection shell(®ions); inExpr = S2SearchUtil::coverAsBSON(&coverer, shell, field.field); // Shell takes ownership of the regions we push in, but they're local variables and // deleting them would be bad. shell.Release(NULL); frsObjBuilder.appendElements(inExpr); } return frsObjBuilder.obj(); }
BSONObj S2NearCursor::makeFRSObject() { BSONObjBuilder frsObjBuilder; frsObjBuilder.appendElements(_filteredQuery); S2RegionCoverer coverer; // Step 1: Make the BSON'd covering for our search annulus. BSONObj inExpr; // Caps are inclusive and inverting a cap includes the border. This means that our // initial _innerRadius of 0 is OK -- we'll still find a point that is exactly at // the start of our search. S2Cap innerCap = S2Cap::FromAxisAngle(_nearQuery.centroid, S1Angle::Radians(_innerRadius / _params.radius)); S2Cap invInnerCap = innerCap.Complement(); S2Cap outerCap = S2Cap::FromAxisAngle(_nearQuery.centroid, S1Angle::Radians(_outerRadius / _params.radius)); vector<S2Region*> regions; regions.push_back(&invInnerCap); regions.push_back(&outerCap); S2RegionIntersection shell(®ions); vector<S2CellId> cover; double area = outerCap.area() - innerCap.area(); S2SearchUtil::setCoverLimitsBasedOnArea(area, &coverer, _params.coarsestIndexedLevel); coverer.GetCovering(shell, &cover); LOG(2) << "annulus cover size is " << cover.size() << ", params (" << coverer.min_level() << ", " << coverer.max_level() << ")" << endl; inExpr = S2SearchUtil::coverAsBSON(cover, _nearQuery.field, _params.coarsestIndexedLevel); // Shell takes ownership of the regions we push in, but they're local variables and // deleting them would be bad. shell.Release(NULL); frsObjBuilder.appendElements(inExpr); _params.configureCoverer(&coverer); // Cover the indexed geo components of the query. for (size_t i = 0; i < _indexedGeoFields.size(); ++i) { vector<S2CellId> cover; coverer.GetCovering(_indexedGeoFields[i].getRegion(), &cover); uassert(16682, "Couldn't generate index keys for geo field " + _indexedGeoFields[i].getField(), cover.size() > 0); BSONObj fieldRange = S2SearchUtil::coverAsBSON(cover, _indexedGeoFields[i].getField(), _params.coarsestIndexedLevel); frsObjBuilder.appendElements(fieldRange); } return frsObjBuilder.obj(); }