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();
    }
Beispiel #3
0
 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();
 }