Status HashIndexCursor::seek(const BSONObj& position) { //Use FieldRangeSet to parse the query into a vector of intervals //These should be point-intervals if this cursor is ever used //So the FieldInterval vector will be, e.g. <[1,1], [3,3], [6,6]> FieldRangeSet frs( "" , position, true, true ); const vector<FieldInterval>& intervals = frs.range( _hashedField.c_str() ).intervals(); //Construct a new query based on the hashes of the previous point-intervals //e.g. {a : {$in : [ hash(1) , hash(3) , hash(6) ]}} BSONObjBuilder newQueryBuilder; BSONObjBuilder inObj( newQueryBuilder.subobjStart( _hashedField ) ); BSONArrayBuilder inArray( inObj.subarrayStart("$in") ); vector<FieldInterval>::const_iterator i; for( i = intervals.begin(); i != intervals.end(); ++i ){ if ( ! i->equality() ){ _oldCursor.reset( BtreeCursor::make( nsdetails( _descriptor->parentNS()), _descriptor->getOnDisk(), BSON( "" << MINKEY ) , BSON( "" << MAXKEY ) , true , 1 ) ); return Status::OK(); } inArray.append(HashAccessMethod::makeSingleKey(i->_lower._bound, _seed, _hashVersion)); } inArray.done(); inObj.done(); BSONObj newQuery = newQueryBuilder.obj(); // FieldRangeVector needs an IndexSpec so we make it one. BSONObjBuilder specBuilder; BSONObjIterator it(_descriptor->keyPattern()); while (it.more()) { BSONElement e = it.next(); specBuilder.append(e.fieldName(), 1); } BSONObj spec = specBuilder.obj(); IndexSpec specForFRV(spec); //Use the point-intervals of the new query to create a Btree cursor FieldRangeSet newfrs( "" , newQuery , true, true ); shared_ptr<FieldRangeVector> newVector( new FieldRangeVector( newfrs , specForFRV, 1 ) ); _oldCursor.reset( BtreeCursor::make(nsdetails(_descriptor->parentNS()), _descriptor->getOnDisk(), newVector, 0, 1)); return Status::OK(); }
void S2SimpleCursor::seek(const BSONObj& query, const vector<GeoQuery>& regions) { _nscanned = 0; _matchTested = 0; _geoTested = 0; _fields = regions; _seen = unordered_set<DiskLoc, DiskLoc::Hasher>(); BSONObjBuilder geoFieldsToNuke; for (size_t i = 0; i < _fields.size(); ++i) { geoFieldsToNuke.append(_fields[i].getField(), ""); } // false means we want to filter OUT geoFieldsToNuke, not filter to include only that. _filteredQuery = query.filterFieldsUndotted(geoFieldsToNuke.obj(), false); // FieldRangeVector needs an IndexSpec so we make it one. BSONObjBuilder specBuilder; BSONObjIterator i(_descriptor->keyPattern()); while (i.more()) { BSONElement e = i.next(); specBuilder.append(e.fieldName(), 1); } BSONObj spec = specBuilder.obj(); IndexSpec specForFRV(spec); BSONObj frsObj; BSONObjBuilder frsObjBuilder; frsObjBuilder.appendElements(_filteredQuery); S2RegionCoverer coverer; for (size_t i = 0; i < _fields.size(); ++i) { vector<S2CellId> cover; double area = _fields[i].getRegion().GetRectBound().Area(); S2SearchUtil::setCoverLimitsBasedOnArea(area, &coverer, _params.coarsestIndexedLevel); coverer.GetCovering(_fields[i].getRegion(), &cover); uassert(16759, "No cover ARGH?!", cover.size() > 0); _cellsInCover = cover.size(); BSONObj fieldRange = S2SearchUtil::coverAsBSON(cover, _fields[i].getField(), _params.coarsestIndexedLevel); frsObjBuilder.appendElements(fieldRange); } frsObj = frsObjBuilder.obj(); FieldRangeSet frs(_descriptor->parentNS().c_str(), frsObj, false, false); shared_ptr<FieldRangeVector> frv(new FieldRangeVector(frs, specForFRV, 1)); _btreeCursor.reset(BtreeCursor::make(nsdetails(_descriptor->parentNS()), _descriptor->getOnDisk(), frv, 0, 1)); next(); }
bool S2Cursor::ok() { if (NULL == _btreeCursor.get()) { // FieldRangeVector needs an IndexSpec so we make it one. BSONObjBuilder specBuilder; BSONObjIterator i(_keyPattern); while (i.more()) { BSONElement e = i.next(); specBuilder.append(e.fieldName(), 1); } BSONObj spec = specBuilder.obj(); IndexSpec specForFRV(spec); // All the magic is in makeUnifiedFRS. See below. // A lot of these arguments are opaque. BSONObj frsObj; if (!makeFRSObject(&frsObj)) { return false; } FieldRangeSet frs(_details->parentNS().c_str(), frsObj, false, false); shared_ptr<FieldRangeVector> frv(new FieldRangeVector(frs, specForFRV, 1)); _btreeCursor.reset(BtreeCursor::make(nsdetails(_details->parentNS()), *_details, frv, 0, 1)); return advance(); } return _btreeCursor->ok(); }