S2AccessMethod::S2AccessMethod(IndexDescriptor *descriptor) : BtreeBasedAccessMethod(descriptor) { // Set up basic params. _params.maxKeysPerInsert = 200; // This is advisory. _params.maxCellsInCovering = 50; // Near distances are specified in meters...sometimes. _params.radius = S2IndexingParams::kRadiusOfEarthInMeters; // These are not advisory. _params.finestIndexedLevel = configValueWithDefault(descriptor, "finestIndexedLevel", S2::kAvgEdge.GetClosestLevel(500.0 / _params.radius)); _params.coarsestIndexedLevel = configValueWithDefault(descriptor, "coarsestIndexedLevel", S2::kAvgEdge.GetClosestLevel(100 * 1000.0 / _params.radius)); uassert(16747, "coarsestIndexedLevel must be >= 0", _params.coarsestIndexedLevel >= 0); uassert(16748, "finestIndexedLevel must be <= 30", _params.finestIndexedLevel <= 30); uassert(16749, "finestIndexedLevel must be >= coarsestIndexedLevel", _params.finestIndexedLevel >= _params.coarsestIndexedLevel); int geoFields = 0; // Categorize the fields we're indexing and make sure we have a geo field. BSONObjIterator i(descriptor->keyPattern()); while (i.more()) { BSONElement e = i.next(); if (e.type() == String && S2IndexingParams::SPHERE_2D_NAME == e.valuestr()) { ++geoFields; } } uassert(16750, "Expect at least one geo field, spec=" + descriptor->keyPattern().toString(), geoFields >= 1); }
virtual IndexType* generate(const IndexSpec* spec) const { S2IndexingParams params; params.maxKeysPerInsert = 200; // This is advisory. params.maxCellsInCovering = 50; // Near distances are specified in meters...sometimes. params.radius = S2IndexingParams::kRadiusOfEarthInMeters; // These are not advisory. params.finestIndexedLevel = configValueWithDefault(spec, "finestIndexedLevel", S2::kAvgEdge.GetClosestLevel(500.0 / params.radius)); params.coarsestIndexedLevel = configValueWithDefault(spec, "coarsestIndexedLevel", S2::kAvgEdge.GetClosestLevel(100 * 1000.0 / params.radius)); uassert(16687, "coarsestIndexedLevel must be >= 0", params.coarsestIndexedLevel >= 0); uassert(16688, "finestIndexedLevel must be <= 30", params.finestIndexedLevel <= 30); uassert(16689, "finestIndexedLevel must be >= coarsestIndexedLevel", params.finestIndexedLevel >= params.coarsestIndexedLevel); return new S2IndexType(SPHERE_2D_NAME, this, spec, params); }
S2AccessMethod::S2AccessMethod(IndexCatalogEntry* btreeState) : BtreeBasedAccessMethod(btreeState) { const IndexDescriptor* descriptor = btreeState->descriptor(); // Set up basic params. _params.maxKeysPerInsert = 200; // This is advisory. _params.maxCellsInCovering = 50; // Near distances are specified in meters...sometimes. _params.radius = kRadiusOfEarthInMeters; // These are not advisory. _params.finestIndexedLevel = configValueWithDefault(descriptor, "finestIndexedLevel", S2::kAvgEdge.GetClosestLevel(500.0 / _params.radius)); _params.coarsestIndexedLevel = configValueWithDefault(descriptor, "coarsestIndexedLevel", S2::kAvgEdge.GetClosestLevel(100 * 1000.0 / _params.radius)); uassert(16747, "coarsestIndexedLevel must be >= 0", _params.coarsestIndexedLevel >= 0); uassert(16748, "finestIndexedLevel must be <= 30", _params.finestIndexedLevel <= 30); uassert(16749, "finestIndexedLevel must be >= coarsestIndexedLevel", _params.finestIndexedLevel >= _params.coarsestIndexedLevel); int geoFields = 0; // Categorize the fields we're indexing and make sure we have a geo field. BSONObjIterator i(descriptor->keyPattern()); while (i.more()) { BSONElement e = i.next(); if (e.type() == String && IndexNames::GEO_2DSPHERE == e.String() ) { ++geoFields; } else { // We check for numeric in 2d, so that's the check here uassert( 16823, (string)"Cannot use " + IndexNames::GEO_2DSPHERE + " index with other special index types: " + e.toString(), e.isNumber() ); } } uassert(16750, "Expect at least one geo field, spec=" + descriptor->keyPattern().toString(), geoFields >= 1); }
TwoDAccessMethod::TwoDAccessMethod(BtreeInMemoryState* btreeState) : BtreeBasedAccessMethod(btreeState) { const IndexDescriptor* descriptor = btreeState->descriptor(); BSONObjIterator i(descriptor->keyPattern()); while (i.more()) { BSONElement e = i.next(); if (e.type() == String && IndexNames::GEO_2D == e.valuestr()) { uassert(16800, "can't have 2 geo fields", _params.geo.size() == 0); uassert(16801, "2d has to be first in index", _params.other.size() == 0); _params.geo = e.fieldName(); } else { int order = 1; if (e.isNumber()) { order = static_cast<int>(e.Number()); } _params.other.push_back(make_pair(e.fieldName(), order)); } } uassert(16802, "no geo field specified", _params.geo.size()); double bits = configValueWithDefault(descriptor, "bits", 26); // for lat/long, ~ 1ft uassert(16803, "bits in geo index must be between 1 and 32", bits > 0 && bits <= 32); GeoHashConverter::Parameters params; params.bits = static_cast<unsigned>(bits); params.max = configValueWithDefault(descriptor, "max", 180.0); params.min = configValueWithDefault(descriptor, "min", -180.0); double numBuckets = (1024 * 1024 * 1024 * 4.0); params.scaling = numBuckets / (params.max - params.min); _params.geoHashConverter.reset(new GeoHashConverter(params)); BSONObjBuilder b; b.appendNull(""); _nullObj = b.obj(); _nullElt = _nullObj.firstElement(); }