예제 #1
0
파일: geonear.cpp 프로젝트: ChowZenki/mongo
        bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            string ns = dbname + "." + cmdObj.firstElement().valuestr();
            NamespaceDetails *d = nsdetails(ns);

            if (NULL == d) {
                errmsg = "can't find ns";
                return false;
            }

            GeoNearArguments commonArgs(cmdObj);
            if (commonArgs.numWanted < 0) {
                errmsg = "numWanted must be >= 0";
                return false;
            }

            vector<int> idxs;

            d->findIndexByType(IndexNames::GEO_2D, idxs);
            if (idxs.size() > 1) {
                errmsg = "more than one 2d index, not sure which to run geoNear on";
                return false;
            }

            unordered_map<string, double> statsMap;

            if (1 == idxs.size()) {
                result.append("ns", ns);
                twod_internal::TwoDGeoNearRunner::run2DGeoNear(d, idxs[0], cmdObj, commonArgs,
                                                               errmsg, result, &statsMap);
                BSONObjBuilder stats(result.subobjStart("stats"));
                for (unordered_map<string, double>::const_iterator it = statsMap.begin();
                     it != statsMap.end(); ++it) {
                    stats.append(it->first, it->second);
                }
                stats.append("time", cc().curop()->elapsedMillis());
                stats.done();
                return true;
            }

            d->findIndexByType(IndexNames::GEO_2DSPHERE, idxs);
            if (idxs.size() > 1) {
                errmsg = "more than one 2dsphere index, not sure which to run geoNear on";
                return false;
            }

            if (1 == idxs.size()) {
                result.append("ns", ns);
                run2DSphereGeoNear(d, idxs[0], cmdObj, commonArgs, errmsg, result);
                return true;
            }

            errmsg = "no geo indices for geoNear";
            return false;
        }
예제 #2
0
        bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            string ns = dbname + "." + cmdObj.firstElement().valuestr();
            NamespaceDetails *d = nsdetails(ns);

            if (NULL == d) {
                errmsg = "can't find ns";
                return false;
            }

            GeoNearArguments commonArgs(cmdObj);
            if (commonArgs.numWanted < 0) {
                errmsg = "numWanted must be >= 0";
                return false;
            }

            vector<int> idxs;

            d->findIndexByType("2d", idxs);
            if (idxs.size() > 1) {
                errmsg = "more than one 2d index, not sure which to run geoNear on";
                return false;
            }

            if (1 == idxs.size()) {
                result.append("ns", ns);
                return run2DGeoNear(d->idx(idxs[0]), cmdObj, commonArgs, errmsg, result);
            }

            d->findIndexByType("2dsphere", idxs);
            if (idxs.size() > 1) {
                errmsg = "more than one 2dsphere index, not sure which to run geoNear on";
                return false;
            }

            if (1 == idxs.size()) {
                result.append("ns", ns);
                return run2DSphereGeoNear(d->idx(idxs[0]), cmdObj, commonArgs, errmsg, result);
            }

            errmsg = "no geo indices for geoNear";
            return false;
        }
예제 #3
0
파일: haystack.cpp 프로젝트: Hasib100/mongo
        bool run(const string& dbname, BSONObj& cmdObj, int,
                 string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            string ns = dbname + "." + cmdObj.firstElement().valuestr();

            NamespaceDetails *nsd = nsdetails(ns);
            if (NULL == nsd) {
                errmsg = "can't find ns";
                return false;
            }

            vector<int> idxs;
            nsd->findIndexByType(GEOSEARCHNAME, idxs);
            if (idxs.size() == 0) {
                errmsg = "no geoSearch index";
                return false;
            }
            if (idxs.size() > 1) {
                errmsg = "more than 1 geosearch index";
                return false;
            }

            BSONElement nearElt = cmdObj["near"];
            BSONElement maxDistance = cmdObj["maxDistance"];
            BSONElement search = cmdObj["search"];

            uassert(13318, "near needs to be an array", nearElt.isABSONObj());
            uassert(13319, "maxDistance needs a number", maxDistance.isNumber());
            uassert(13320, "search needs to be an object", search.type() == Object);

            unsigned limit = 50;
            if (cmdObj["limit"].isNumber())
                limit = static_cast<unsigned>(cmdObj["limit"].numberInt());

            int idxNum = idxs[0];
            IndexDetails& id = nsd->idx(idxNum);
            if (CatalogHack::testIndexMigration()) {
                auto_ptr<IndexDescriptor> desc(CatalogHack::getDescriptor(nsd, idxNum));
                auto_ptr<HaystackAccessMethod> ham(new HaystackAccessMethod(desc.get()));
                ham->searchCommand(nearElt.Obj(), maxDistance.numberDouble(), search.Obj(),
                                   &result, limit);
            } else {
                GeoHaystackSearchIndex *si =
                    static_cast<GeoHaystackSearchIndex*>(id.getSpec().getType());
                verify(&id == si->getDetails());
                si->searchCommand(nsd, nearElt.Obj(), maxDistance.numberDouble(), search.Obj(),
                                  result, limit);
            }
            return 1;
        }
예제 #4
0
        bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {

            string ns = dbname + "." + cmdObj.firstElement().valuestr();

            NamespaceDetails * d = nsdetails( ns.c_str() );
            if ( ! d ) {
                errmsg = "can't find ns";
                return false;
            }

            vector<int> idxs;
            d->findIndexByType( GEOSEARCHNAME , idxs );
            if ( idxs.size() == 0 ) {
                errmsg = "no geoSearch index";
                return false;
            }
            if ( idxs.size() > 1 ) {
                errmsg = "more than 1 geosearch index";
                return false;
            }

            int idxNum = idxs[0];

            IndexDetails& id = d->idx( idxNum );
            GeoHaystackSearchIndex * si = (GeoHaystackSearchIndex*)id.getSpec().getType();
            verify( &id == si->getDetails() );

            BSONElement n = cmdObj["near"];
            BSONElement maxDistance = cmdObj["maxDistance"];
            BSONElement search = cmdObj["search"];

            uassert( 13318 , "near needs to be an array" , n.isABSONObj() );
            uassert( 13319 , "maxDistance needs a number" , maxDistance.isNumber() );
            uassert( 13320 , "search needs to be an object" , search.type() == Object );

            unsigned limit = 50;
            if ( cmdObj["limit"].isNumber() )
                limit = (unsigned)cmdObj["limit"].numberInt();

            si->searchCommand( d , idxNum , n.Obj() , maxDistance.numberDouble() , search.Obj() , result , limit );

            return 1;
        }
예제 #5
0
    PlanStage* buildStages(const string& ns, const QuerySolutionNode* root, WorkingSet* ws) {
        if (STAGE_COLLSCAN == root->getType()) {
            const CollectionScanNode* csn = static_cast<const CollectionScanNode*>(root);
            CollectionScanParams params;
            params.ns = csn->name;
            params.tailable = csn->tailable;
            params.direction = (csn->direction == 1) ? CollectionScanParams::FORWARD
                                                     : CollectionScanParams::BACKWARD;
            return new CollectionScan(params, ws, csn->filter.get());
        }
        else if (STAGE_IXSCAN == root->getType()) {
            const IndexScanNode* ixn = static_cast<const IndexScanNode*>(root);
            //
            // XXX XXX
            // Given that this grabs data from the catalog, we must do this inside of a lock.
            // We should change this to take a (ns, index key pattern) pair so that the params
            // don't involve any on-disk data, just descriptions thereof.
            // XXX XXX
            //
            IndexScanParams params;
            NamespaceDetails* nsd = nsdetails(ns.c_str());
            if (NULL == nsd) {
                warning() << "Can't ixscan null ns " << ns << endl;
                return NULL;
            }
            int idxNo = nsd->findIndexByKeyPattern(ixn->indexKeyPattern);
            if (-1 == idxNo) {
                warning() << "Can't find idx " << ixn->indexKeyPattern.toString()
                          << "in ns " << ns << endl;
                return NULL;
            }
            params.descriptor = CatalogHack::getDescriptor(nsd, idxNo);
            params.bounds = ixn->bounds;
            params.direction = ixn->direction;
            params.limit = ixn->limit;
            return new IndexScan(params, ws, ixn->filter.get());
        }
        else if (STAGE_FETCH == root->getType()) {
            const FetchNode* fn = static_cast<const FetchNode*>(root);
            PlanStage* childStage = buildStages(ns, fn->child.get(), ws);
            if (NULL == childStage) { return NULL; }
            return new FetchStage(ws, childStage, fn->filter.get());
        }
        else if (STAGE_SORT == root->getType()) {
            const SortNode* sn = static_cast<const SortNode*>(root);
            PlanStage* childStage = buildStages(ns, sn->child.get(), ws);
            if (NULL == childStage) { return NULL; }
            SortStageParams params;
            params.pattern = sn->pattern;
            return new SortStage(params, ws, childStage);
        }
        else if (STAGE_PROJECTION == root->getType()) {
            const ProjectionNode* pn = static_cast<const ProjectionNode*>(root);
            PlanStage* childStage = buildStages(ns, pn->child.get(), ws);
            if (NULL == childStage) { return NULL; }
            return new ProjectionStage(pn->projection, ws, childStage, NULL);
        }
        else if (STAGE_LIMIT == root->getType()) {
            const LimitNode* ln = static_cast<const LimitNode*>(root);
            PlanStage* childStage = buildStages(ns, ln->child.get(), ws);
            if (NULL == childStage) { return NULL; }
            return new LimitStage(ln->limit, ws, childStage);
        }
        else if (STAGE_SKIP == root->getType()) {
            const SkipNode* sn = static_cast<const SkipNode*>(root);
            PlanStage* childStage = buildStages(ns, sn->child.get(), ws);
            if (NULL == childStage) { return NULL; }
            return new SkipStage(sn->skip, ws, childStage);
        }
        else if (STAGE_AND_HASH == root->getType()) {
            const AndHashNode* ahn = static_cast<const AndHashNode*>(root);
            auto_ptr<AndHashStage> ret(new AndHashStage(ws, ahn->filter.get()));
            for (size_t i = 0; i < ahn->children.size(); ++i) {
                PlanStage* childStage = buildStages(ns, ahn->children[i], ws);
                if (NULL == childStage) { return NULL; }
                ret->addChild(childStage);
            }
            return ret.release();
        }
        else if (STAGE_OR == root->getType()) {
            const OrNode * orn = static_cast<const OrNode*>(root);
            auto_ptr<OrStage> ret(new OrStage(ws, orn->dedup, orn->filter.get()));
            for (size_t i = 0; i < orn->children.size(); ++i) {
                PlanStage* childStage = buildStages(ns, orn->children[i], ws);
                if (NULL == childStage) { return NULL; }
                ret->addChild(childStage);
            }
            return ret.release();
        }
        else if (STAGE_AND_SORTED == root->getType()) {
            const AndSortedNode* asn = static_cast<const AndSortedNode*>(root);
            auto_ptr<AndSortedStage> ret(new AndSortedStage(ws, asn->filter.get()));
            for (size_t i = 0; i < asn->children.size(); ++i) {
                PlanStage* childStage = buildStages(ns, asn->children[i], ws);
                if (NULL == childStage) { return NULL; }
                ret->addChild(childStage);
            }
            return ret.release();
        }
        else if (STAGE_SORT_MERGE == root->getType()) {
            const MergeSortNode* msn = static_cast<const MergeSortNode*>(root);
            MergeSortStageParams params;
            params.dedup = msn->dedup;
            params.pattern = msn->sort;
            auto_ptr<MergeSortStage> ret(new MergeSortStage(params, ws));
            for (size_t i = 0; i < msn->children.size(); ++i) {
                PlanStage* childStage = buildStages(ns, msn->children[i], ws);
                if (NULL == childStage) { return NULL; }
                ret->addChild(childStage);
            }
            return ret.release();
        }
        else if (STAGE_GEO_2D == root->getType()) {
            const Geo2DNode* node = static_cast<const Geo2DNode*>(root);
            TwoDParams params;
            params.gq = node->gq;
            params.filter = node->filter.get();
            params.indexKeyPattern = node->indexKeyPattern;
            params.ns = ns;
            return new TwoD(params, ws);
        }
        else if (STAGE_GEO_NEAR_2D == root->getType()) {
            const GeoNear2DNode* node = static_cast<const GeoNear2DNode*>(root);
            TwoDNearParams params;
            params.nearQuery = node->nq;
            params.ns = ns;
            params.indexKeyPattern = node->indexKeyPattern;
            params.filter = node->filter.get();
            params.numWanted = node->numWanted;
            // XXX XXX where do we grab this from??  the near query...modify geo parser... :(
            params.uniqueDocs = false;
            // XXX XXX where do we grab this from??  the near query...modify geo parser... :(
            return new TwoDNear(params, ws);
        }
        else if (STAGE_GEO_NEAR_2DSPHERE == root->getType()) {
            const GeoNear2DSphereNode* node = static_cast<const GeoNear2DSphereNode*>(root);
            return new S2NearStage(ns, node->indexKeyPattern, node->nq, node->baseBounds,
                                   node->filter.get(), ws);
        }
        else if (STAGE_TEXT == root->getType()) {
            const TextNode* node = static_cast<const TextNode*>(root);

            NamespaceDetails* nsd = nsdetails(ns.c_str());
            if (NULL == nsd) { return NULL; }
            vector<int> idxMatches;
            nsd->findIndexByType("text", idxMatches);
            if (1 != idxMatches.size()) { return NULL; }
            IndexDescriptor* index = CatalogHack::getDescriptor(nsd, idxMatches[0]);
            auto_ptr<FTSAccessMethod> fam(new FTSAccessMethod(index));
            TextStageParams params(fam->getSpec());

            params.ns = ns;
            params.index = index;
            params.spec = fam->getSpec();
            params.limit = node->_numWanted;
            Status s = fam->getSpec().getIndexPrefix(BSONObj(), &params.indexPrefix);
            if (!s.isOK()) { return NULL; }

            string language = ("" == node->_language
                               ? fam->getSpec().defaultLanguage()
                               : node->_language);

            FTSQuery ftsq;
            Status parseStatus = ftsq.parse(node->_query, language);
            if (!parseStatus.isOK()) { return NULL; }
            params.query = ftsq;

            return new TextStage(params, ws, node->_filter.get());
        }
        else {
            stringstream ss;
            root->appendToString(&ss, 0);
            warning() << "Could not build exec tree for node " << ss.str() << endl;
            return NULL;
        }
    }