summaryrefslogtreecommitdiff
path: root/src/mongo/db/index/expression_params.cpp
diff options
context:
space:
mode:
authorKevin Albertson <kevin.albertson@10gen.com>2015-06-11 10:30:46 -0400
committerKevin Albertson <kevin.albertson@10gen.com>2015-07-17 12:07:32 -0400
commitc33f68518b06e6b98596a8133d097e75d8431293 (patch)
tree49757af46288b63155e554f5bcc64b026ef494f4 /src/mongo/db/index/expression_params.cpp
parent0db35ed67ac5c22969cc674a43bf741f85cd9bdc (diff)
downloadmongo-c33f68518b06e6b98596a8133d097e75d8431293.tar.gz
SERVER-19097 Add version 3 to 2dsphere index
Diffstat (limited to 'src/mongo/db/index/expression_params.cpp')
-rw-r--r--src/mongo/db/index/expression_params.cpp177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/mongo/db/index/expression_params.cpp b/src/mongo/db/index/expression_params.cpp
new file mode 100644
index 00000000000..778f5c03010
--- /dev/null
+++ b/src/mongo/db/index/expression_params.cpp
@@ -0,0 +1,177 @@
+/**
+ * Copyright (C) 2015 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/index/expression_params.h"
+
+#include "mongo/bson/util/bson_extract.h"
+#include "mongo/db/geo/geoconstants.h"
+#include "mongo/db/hasher.h"
+#include "mongo/db/index_names.h"
+#include "mongo/db/index/2d_common.h"
+#include "mongo/db/index/s2_indexing_params.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+using mongoutils::str::stream;
+
+void ExpressionParams::parseTwoDParams(const BSONObj& infoObj, TwoDIndexingParams* out) {
+ BSONObjIterator i(infoObj.getObjectField("key"));
+
+ while (i.more()) {
+ BSONElement e = i.next();
+ if (e.type() == String && IndexNames::GEO_2D == e.valuestr()) {
+ uassert(16800, "can't have 2 geo fields", out->geo.size() == 0);
+ uassert(16801, "2d has to be first in index", out->other.size() == 0);
+ out->geo = e.fieldName();
+ } else {
+ int order = 1;
+ if (e.isNumber()) {
+ order = static_cast<int>(e.Number());
+ }
+ out->other.push_back(std::make_pair(e.fieldName(), order));
+ }
+ }
+
+ uassert(16802, "no geo field specified", out->geo.size());
+
+ GeoHashConverter::Parameters hashParams;
+ Status paramStatus = GeoHashConverter::parseParameters(infoObj, &hashParams);
+ uassertStatusOK(paramStatus);
+
+ out->geoHashConverter.reset(new GeoHashConverter(hashParams));
+}
+
+void ExpressionParams::parseHashParams(const BSONObj& infoObj,
+ HashSeed* seedOut,
+ int* versionOut,
+ std::string* fieldOut) {
+ // Default _seed to DEFAULT_HASH_SEED if "seed" is not included in the index spec
+ // or if the value of "seed" is not a number
+
+ // *** WARNING ***
+ // Choosing non-default seeds will invalidate hashed sharding
+ // Changing the seed default will break existing indexes and sharded collections
+ if (infoObj["seed"].eoo()) {
+ *seedOut = BSONElementHasher::DEFAULT_HASH_SEED;
+ } else {
+ *seedOut = infoObj["seed"].numberInt();
+ }
+
+ // In case we have hashed indexes based on other hash functions in the future, we store
+ // a hashVersion number. If hashVersion changes, "makeSingleHashKey" will need to change
+ // accordingly. Defaults to 0 if "hashVersion" is not included in the index spec or if
+ // the value of "hashversion" is not a number
+ *versionOut = infoObj["hashVersion"].numberInt();
+
+ // Get the hashfield name
+ BSONElement firstElt = infoObj.getObjectField("key").firstElement();
+ massert(16765, "error: no hashed index field", firstElt.str().compare(IndexNames::HASHED) == 0);
+ *fieldOut = firstElt.fieldName();
+}
+
+void ExpressionParams::parseHaystackParams(const BSONObj& infoObj,
+ std::string* geoFieldOut,
+ std::vector<std::string>* otherFieldsOut,
+ double* bucketSizeOut) {
+ BSONElement e = infoObj["bucketSize"];
+ uassert(16777, "need bucketSize", e.isNumber());
+ *bucketSizeOut = e.numberDouble();
+ uassert(16769, "bucketSize cannot be zero", *bucketSizeOut != 0.0);
+
+ // Example:
+ // db.foo.ensureIndex({ pos : "geoHaystack", type : 1 }, { bucketSize : 1 })
+ BSONObjIterator i(infoObj.getObjectField("key"));
+ while (i.more()) {
+ BSONElement e = i.next();
+ if (e.type() == String && IndexNames::GEO_HAYSTACK == e.valuestr()) {
+ uassert(16770, "can't have more than one geo field", geoFieldOut->size() == 0);
+ uassert(16771, "the geo field has to be first in index", otherFieldsOut->size() == 0);
+ *geoFieldOut = e.fieldName();
+ } else {
+ uassert(16772,
+ "geoSearch can only have 1 non-geo field for now",
+ otherFieldsOut->size() == 0);
+ otherFieldsOut->push_back(e.fieldName());
+ }
+ }
+}
+
+void ExpressionParams::parse2dsphereParams(const BSONObj& infoObj, S2IndexingParams* out) {
+ // Set up basic params.
+ out->maxKeysPerInsert = 200;
+
+ // This is advisory.
+ out->maxCellsInCovering = 50;
+
+ // Near distances are specified in meters...sometimes.
+ out->radius = kRadiusOfEarthInMeters;
+
+
+ static const std::string kIndexVersionFieldName("2dsphereIndexVersion");
+ static const std::string kFinestIndexedLevel("finestIndexedLevel");
+ static const std::string kCoarsestIndexedLevel("coarsestIndexedLevel");
+
+ long long finestIndexedLevel, coarsestIndexedLevel, indexVersion;
+
+ bsonExtractIntegerFieldWithDefault(infoObj,
+ kFinestIndexedLevel,
+ S2::kAvgEdge.GetClosestLevel(500.0 / out->radius),
+ &finestIndexedLevel);
+ bsonExtractIntegerFieldWithDefault(infoObj,
+ kCoarsestIndexedLevel,
+ S2::kAvgEdge.GetClosestLevel(100 * 1000.0 / out->radius),
+ &coarsestIndexedLevel);
+
+ // These are not advisory.
+ out->finestIndexedLevel = finestIndexedLevel;
+ out->coarsestIndexedLevel = coarsestIndexedLevel;
+
+ // Determine which version of this index we're using. If none was set in the descriptor,
+ // assume S2_INDEX_VERSION_1 (alas, the first version predates the existence of the version
+ // field).
+ bsonExtractIntegerFieldWithDefault(
+ infoObj, kIndexVersionFieldName, S2_INDEX_VERSION_1, &indexVersion);
+
+ out->indexVersion = static_cast<S2IndexVersion>(indexVersion);
+
+ uassert(16747, "coarsestIndexedLevel must be >= 0", out->coarsestIndexedLevel >= 0);
+ uassert(16748, "finestIndexedLevel must be <= 30", out->finestIndexedLevel <= 30);
+ uassert(16749,
+ "finestIndexedLevel must be >= coarsestIndexedLevel",
+ out->finestIndexedLevel >= out->coarsestIndexedLevel);
+
+
+ massert(17395,
+ stream() << "unsupported geo index version { " << kIndexVersionFieldName << " : "
+ << out->indexVersion << " }, only support versions: [" << S2_INDEX_VERSION_1
+ << "," << S2_INDEX_VERSION_2 << "," << S2_INDEX_VERSION_3 << "]",
+ out->indexVersion == S2_INDEX_VERSION_3 || out->indexVersion == S2_INDEX_VERSION_2 ||
+ out->indexVersion == S2_INDEX_VERSION_1);
+}
+} // namespace mongo