Example #1
0
    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(&regions);
            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();
    }
Example #2
0
    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(&regions);
        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();
    }