summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorMax Hirschhorn <max.hirschhorn@mongodb.com>2016-06-03 13:26:35 -0400
committerMax Hirschhorn <max.hirschhorn@mongodb.com>2016-06-03 13:26:35 -0400
commitcecbe424d32cbb475d9b0384d29b98a9fba9c89f (patch)
tree0ce2632b078fee8865f15a56cf07c684a8260c21 /src/mongo/db
parent8900002b731358b0beedadb2ceb4e3156de402b6 (diff)
downloadmongo-cecbe424d32cbb475d9b0384d29b98a9fba9c89f.tar.gz
SERVER-23114 Move functions involving dotted paths to separate library.
The ability to specify a dotted path (e.g. "a.b") to traverse through embedded objects and array elements isn't defined in the BSON specification and so it doesn't belong in our BSON library. The following functions have been defined within a 'dotted_path_support' namespace and accept an additional BSONObj as their first argument to replace the associated method on the BSONObj class. - extractElementAtPath() is functionally equivalent to BSONObj::getFieldDotted(). - extractElementAtPathOrArrayAlongPath() is functionally equivalent to BSONObj::getFieldDottedOrArray(). - extractAllElementsAlongPath() is functionally equivalent to BSONObj::getFieldsDotted(). - extractElementsBasedOnTemplate() is functionally equivalent to BSONObj::extractFields(). - compareObjectsAccordingToSort() is functionally equivalent to BSONObj::woSortOrder().
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/SConscript2
-rw-r--r--src/mongo/db/bson/SConscript23
-rw-r--r--src/mongo/db/bson/dotted_path_support.cpp211
-rw-r--r--src/mongo/db/bson/dotted_path_support.h153
-rw-r--r--src/mongo/db/bson/dotted_path_support_test.cpp219
-rw-r--r--src/mongo/db/commands/distinct.cpp5
-rw-r--r--src/mongo/db/commands/mr.cpp7
-rw-r--r--src/mongo/db/exec/SConscript2
-rw-r--r--src/mongo/db/exec/geo_near.cpp5
-rw-r--r--src/mongo/db/exec/group.cpp5
-rw-r--r--src/mongo/db/exec/update.cpp4
-rw-r--r--src/mongo/db/exec/working_set.cpp5
-rw-r--r--src/mongo/db/fts/SConscript1
-rw-r--r--src/mongo/db/fts/fts_index_format.cpp7
-rw-r--r--src/mongo/db/fts/fts_spec.cpp4
-rw-r--r--src/mongo/db/fts/fts_spec_legacy.cpp7
-rw-r--r--src/mongo/db/geo/SConscript1
-rw-r--r--src/mongo/db/geo/geoparser.cpp13
-rw-r--r--src/mongo/db/index/SConscript1
-rw-r--r--src/mongo/db/index/btree_key_generator.cpp19
-rw-r--r--src/mongo/db/index/btree_key_generator.h6
-rw-r--r--src/mongo/db/index/expression_keys_private.cpp18
-rw-r--r--src/mongo/db/index/haystack_access_method.cpp5
-rw-r--r--src/mongo/db/index/haystack_access_method_internal.h5
-rw-r--r--src/mongo/db/ops/SConscript1
-rw-r--r--src/mongo/db/ops/modifier_push_sorter.h6
-rw-r--r--src/mongo/db/ops/modifier_push_test.cpp7
-rw-r--r--src/mongo/db/pipeline/SConscript2
-rw-r--r--src/mongo/db/pipeline/document.h2
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.cpp7
-rw-r--r--src/mongo/db/pipeline/pipeline.cpp5
-rw-r--r--src/mongo/db/query/SConscript1
-rw-r--r--src/mongo/db/query/planner_access.cpp7
-rw-r--r--src/mongo/db/query/planner_analysis.cpp5
-rw-r--r--src/mongo/db/query/query_planner.cpp7
-rw-r--r--src/mongo/db/repl/SConscript1
-rw-r--r--src/mongo/db/repl/replication_executor_test.cpp15
-rw-r--r--src/mongo/db/s/SConscript1
-rw-r--r--src/mongo/db/s/check_sharding_index_command.cpp5
-rw-r--r--src/mongo/db/s/split_vector_command.cpp11
-rw-r--r--src/mongo/db/storage/SConscript1
-rw-r--r--src/mongo/db/storage/storage_engine_metadata.cpp7
-rw-r--r--src/mongo/db/storage/wiredtiger/SConscript3
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp8
44 files changed, 764 insertions, 66 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 752b6c683fc..94464e37819 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -7,6 +7,7 @@ Import("wiredtiger")
env.SConscript(
dirs=[
'auth',
+ 'bson',
'catalog',
'commands',
'concurrency',
@@ -694,6 +695,7 @@ serveronlyEnv = env.Clone()
serveronlyEnv.InjectThirdPartyIncludePaths(libraries=['snappy'])
serveronlyLibdeps = [
"$BUILD_DIR/mongo/client/parallel",
+ "$BUILD_DIR/mongo/db/bson/dotted_path_support",
"$BUILD_DIR/mongo/executor/network_interface_factory",
"$BUILD_DIR/mongo/s/catalog/replset/catalog_manager_replica_set",
"$BUILD_DIR/mongo/s/client/sharding_connection_hook",
diff --git a/src/mongo/db/bson/SConscript b/src/mongo/db/bson/SConscript
new file mode 100644
index 00000000000..38c42957046
--- /dev/null
+++ b/src/mongo/db/bson/SConscript
@@ -0,0 +1,23 @@
+# -*- mode: python -*-
+
+Import("env")
+
+env.Library(
+ target="dotted_path_support",
+ source=[
+ "dotted_path_support.cpp",
+ ],
+ LIBDEPS=[
+ "$BUILD_DIR/mongo/base",
+ ],
+)
+
+env.CppUnitTest(
+ target="dotted_path_support_test",
+ source=[
+ "dotted_path_support_test.cpp",
+ ],
+ LIBDEPS=[
+ "dotted_path_support",
+ ],
+)
diff --git a/src/mongo/db/bson/dotted_path_support.cpp b/src/mongo/db/bson/dotted_path_support.cpp
new file mode 100644
index 00000000000..cfb10c5a39f
--- /dev/null
+++ b/src/mongo/db/bson/dotted_path_support.cpp
@@ -0,0 +1,211 @@
+/**
+ * Copyright (C) 2016 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/platform/basic.h"
+
+#include "mongo/db/bson/dotted_path_support.h"
+
+#include <cctype>
+#include <string>
+
+#include "mongo/bson/bsonelement.h"
+#include "mongo/bson/bsonmisc.h"
+#include "mongo/bson/bsonobj.h"
+#include "mongo/bson/bsonobjbuilder.h"
+
+namespace mongo {
+namespace dotted_path_support {
+
+namespace {
+
+const BSONObj kNullObj = BSON("" << BSONNULL);
+const BSONElement kNullElt = kNullObj.firstElement();
+
+template <typename BSONElementColl>
+void _extractAllElementsAlongPath(const BSONObj& obj,
+ StringData path,
+ BSONElementColl& elements,
+ bool expandArrayOnTrailingField) {
+ BSONElement e = obj.getField(path);
+
+ if (e.eoo()) {
+ size_t idx = path.find('.');
+ if (idx != std::string::npos) {
+ StringData left = path.substr(0, idx);
+ StringData next = path.substr(idx + 1, path.size());
+
+ BSONElement e = obj.getField(left);
+
+ if (e.type() == Object) {
+ _extractAllElementsAlongPath(
+ e.embeddedObject(), next, elements, expandArrayOnTrailingField);
+ } else if (e.type() == Array) {
+ bool allDigits = false;
+ if (next.size() > 0 && std::isdigit(next[0])) {
+ unsigned temp = 1;
+ while (temp < next.size() && std::isdigit(next[temp]))
+ temp++;
+ allDigits = temp == next.size() || next[temp] == '.';
+ }
+ if (allDigits) {
+ _extractAllElementsAlongPath(
+ e.embeddedObject(), next, elements, expandArrayOnTrailingField);
+ } else {
+ BSONObjIterator i(e.embeddedObject());
+ while (i.more()) {
+ BSONElement e2 = i.next();
+ if (e2.type() == Object || e2.type() == Array)
+ _extractAllElementsAlongPath(
+ e2.embeddedObject(), next, elements, expandArrayOnTrailingField);
+ }
+ }
+ } else {
+ // do nothing: no match
+ }
+ }
+ } else {
+ if (e.type() == Array && expandArrayOnTrailingField) {
+ BSONObjIterator i(e.embeddedObject());
+ while (i.more())
+ elements.insert(i.next());
+ } else {
+ elements.insert(e);
+ }
+ }
+}
+
+} // namespace
+
+BSONElement extractElementAtPath(const BSONObj& obj, StringData path) {
+ BSONElement e = obj.getField(path);
+ if (e.eoo()) {
+ size_t dot_offset = path.find('.');
+ if (dot_offset != std::string::npos) {
+ StringData left = path.substr(0, dot_offset);
+ StringData right = path.substr(dot_offset + 1);
+ BSONObj sub = obj.getObjectField(left);
+ return sub.isEmpty() ? BSONElement() : extractElementAtPath(sub, right);
+ }
+ }
+
+ return e;
+}
+
+BSONElement extractElementAtPathOrArrayAlongPath(const BSONObj& obj, const char*& path) {
+ const char* p = strchr(path, '.');
+
+ BSONElement sub;
+
+ if (p) {
+ sub = obj.getField(std::string(path, p - path));
+ path = p + 1;
+ } else {
+ sub = obj.getField(path);
+ path = path + strlen(path);
+ }
+
+ if (sub.eoo())
+ return BSONElement();
+ else if (sub.type() == Array || path[0] == '\0')
+ return sub;
+ else if (sub.type() == Object)
+ return extractElementAtPathOrArrayAlongPath(sub.embeddedObject(), path);
+ else
+ return BSONElement();
+}
+
+void extractAllElementsAlongPath(const BSONObj& obj,
+ StringData path,
+ BSONElementSet& elements,
+ bool expandArrayOnTrailingField) {
+ _extractAllElementsAlongPath(obj, path, elements, expandArrayOnTrailingField);
+}
+
+void extractAllElementsAlongPath(const BSONObj& obj,
+ StringData path,
+ BSONElementMSet& elements,
+ bool expandArrayOnTrailingField) {
+ _extractAllElementsAlongPath(obj, path, elements, expandArrayOnTrailingField);
+}
+
+BSONObj extractElementsBasedOnTemplate(const BSONObj& obj,
+ const BSONObj& pattern,
+ bool useNullIfMissing) {
+ // scanandorder.h can make a zillion of these, so we start the allocation very small.
+ BSONObjBuilder b(32);
+ BSONObjIterator i(pattern);
+ while (i.moreWithEOO()) {
+ BSONElement e = i.next();
+ if (e.eoo())
+ break;
+ BSONElement x = extractElementAtPath(obj, e.fieldName());
+ if (!x.eoo())
+ b.appendAs(x, e.fieldName());
+ else if (useNullIfMissing)
+ b.appendNull(e.fieldName());
+ }
+ return b.obj();
+}
+
+int compareObjectsAccordingToSort(const BSONObj& firstObj,
+ const BSONObj& secondObj,
+ const BSONObj& sortKey,
+ bool assumeDottedPaths) {
+ if (firstObj.isEmpty())
+ return secondObj.isEmpty() ? 0 : -1;
+ if (secondObj.isEmpty())
+ return 1;
+
+ uassert(10060, "compareObjectsAccordingToSort() needs a non-empty sortKey", !sortKey.isEmpty());
+
+ BSONObjIterator i(sortKey);
+ while (1) {
+ BSONElement f = i.next();
+ if (f.eoo())
+ return 0;
+
+ BSONElement l = assumeDottedPaths ? extractElementAtPath(firstObj, f.fieldName())
+ : firstObj.getField(f.fieldName());
+ if (l.eoo())
+ l = kNullElt;
+ BSONElement r = assumeDottedPaths ? extractElementAtPath(secondObj, f.fieldName())
+ : secondObj.getField(f.fieldName());
+ if (r.eoo())
+ r = kNullElt;
+
+ int x = l.woCompare(r, false);
+ if (f.number() < 0)
+ x = -x;
+ if (x != 0)
+ return x;
+ }
+ return -1;
+}
+
+} // namespace dotted_path_support
+} // namespace mongo
diff --git a/src/mongo/db/bson/dotted_path_support.h b/src/mongo/db/bson/dotted_path_support.h
new file mode 100644
index 00000000000..9e2a3c9e9d0
--- /dev/null
+++ b/src/mongo/db/bson/dotted_path_support.h
@@ -0,0 +1,153 @@
+/**
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+#include <cstddef>
+#include <set>
+
+#include "mongo/bson/bsonobj.h"
+
+namespace mongo {
+namespace dotted_path_support {
+
+/**
+ * Returns the element at the specified path. This function returns BSONElement() if the element
+ * wasn't found.
+ *
+ * The 'path' can be specified using a dotted notation in order to traverse through embedded objects
+ * and array elements.
+ *
+ * Some examples:
+ *
+ * Consider the document {a: {b: 1}} and the path "a.b". An element with key="b" and value=1 would
+ * be returned.
+ *
+ * Consider the document {a: [{b: 1}]} and the path "a.b". BSONElement() would be returned because
+ * the array value is actually an object with key="0" and value={b: 1}.
+ *
+ * Consider the document {a: [{b: 1}]} and the path "a.0.b". An element with key="b" and value=1
+ * would be returned.
+ */
+BSONElement extractElementAtPath(const BSONObj& obj, StringData path);
+
+/**
+ * Returns the element at the specified path, or the first element with an array value encountered
+ * along the specified path. This function returns BSONElement() if the element wasn't found.
+ *
+ * The 'path' can be specified using a dotted notation in order to traverse through embedded objects
+ * and array elements.
+ *
+ * This function modifies 'path' to be the suffix of the path that follows the first element with an
+ * array value. If no such element is present, then 'path' is set as the empty string.
+ *
+ * Some examples:
+ *
+ * Consider the document {a: {b: [1]}} and the path "a.b". An element with key="b" and value=1
+ * would be returned. 'path' would be changed to the empty string.
+ *
+ * Consider the document {a: [{b: 1}]} and the path "a.b". An element with key="a" and
+ * value=[{b: 1}] would be returned. 'path' would be changed to the string "b".
+ */
+BSONElement extractElementAtPathOrArrayAlongPath(const BSONObj& obj, const char*& path);
+
+/**
+ * Expands arrays along the specified path and adds all elements to the 'elements' set.
+ *
+ * The 'path' can be specified using a dotted notation in order to traverse through embedded objects
+ * and array elements.
+ *
+ * Some examples:
+ *
+ * Consider the document {a: [{b: 1}, {b: 2}]} and the path "a.b". The elements {b: 1} and {b: 2}
+ * would be added to the set.
+ *
+ * Consider the document {a: [{b: [1, 2]}, {b: [2, 3]}]} and the path "a.b". The elements {b: 1},
+ * {b: 2}, and {b: 3} would be added to the set if 'expandArrayOnTrailingField' is true. The
+ * elements {b: [1, 2]} and {b: [2, 3]} would be added to the set if 'expandArrayOnTrailingField'
+ * is false.
+ */
+void extractAllElementsAlongPath(const BSONObj& obj,
+ StringData path,
+ BSONElementSet& elements,
+ bool expandArrayOnTrailingField = true);
+
+void extractAllElementsAlongPath(const BSONObj& obj,
+ StringData path,
+ BSONElementMSet& elements,
+ bool expandArrayOnTrailingField = true);
+
+/**
+ * Returns an owned BSONObj with elements in the same order as they appear in the 'pattern' object
+ * and values extracted from 'obj'.
+ *
+ * The keys of the elements in the 'pattern' object can be specified using a dotted notation in
+ * order to traverse through embedded objects and array elements. The values of the elements in the
+ * 'pattern' object are ignored.
+ *
+ * If 'useNullIfMissing' is true and the key in the 'pattern' object isn't present in 'obj', then a
+ * null value is appended to the returned value instead.
+ *
+ * Some examples:
+ *
+ * Consider the document {a: 1, b: 1} and the template {b: ""}. The object {b: 1} would be
+ * returned.
+ *
+ * Consider the document {a: {b: 1}} and the template {"a.b": ""}. The object {"a.b": 1} would be
+ * returned.
+ *
+ * Consider the document {b: 1} and the template {a: "", b: ""}. The object {a: null, b: 1} would
+ * be returned if 'useNullIfMissing' is true. The object {b: 1} would be returned if
+ * 'useNullIfMissing' is false.
+ */
+BSONObj extractElementsBasedOnTemplate(const BSONObj& obj,
+ const BSONObj& pattern,
+ bool useNullIfMissing = false);
+
+/**
+ * Compares two objects according to order of elements in the 'sortKey' object. This function
+ * returns -1 if 'firstObj' < 'secondObj' according to 'sortKey', 0 if 'firstObj' == 'secondObj'
+ * according to 'sortKey', and 1 if 'firstObj' > 'secondObj' according to 'sortKey'.
+ *
+ * If 'assumeDottedPaths' is true, then extractElementAtPath() is used to get the element associated
+ * with the key of an element in the 'sortKey' object. If 'assumeDottedPaths' is false, then
+ * BSONObj::getField() is used to get the element associated with the key of an element in the
+ * 'sortKey' object. BSONObj::getField() searches the object for the key verbatim and does no
+ * special handling to traverse through embedded objects and array elements when a "." character is
+ * specified.
+ *
+ * Unlike with BSONObj::woCompare(), the elements don't need to be in the same order between
+ * 'firstObj' and 'secondObj'.
+ */
+int compareObjectsAccordingToSort(const BSONObj& firstObj,
+ const BSONObj& secondObj,
+ const BSONObj& sortKey,
+ bool assumeDottedPaths = false);
+
+} // namespace dotted_path_support
+} // namespace mongo
diff --git a/src/mongo/db/bson/dotted_path_support_test.cpp b/src/mongo/db/bson/dotted_path_support_test.cpp
new file mode 100644
index 00000000000..78d3253d8b5
--- /dev/null
+++ b/src/mongo/db/bson/dotted_path_support_test.cpp
@@ -0,0 +1,219 @@
+/**
+ * Copyright (C) 2016 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/platform/basic.h"
+
+#include <vector>
+
+#include "mongo/bson/bsonelement.h"
+#include "mongo/bson/bsonmisc.h"
+#include "mongo/bson/bsonobj.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/bson/dotted_path_support.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+namespace {
+
+namespace dps = ::mongo::dotted_path_support;
+
+TEST(DottedPathSupport, CompareObjectsAccordingToSort) {
+ ASSERT_LT(dps::compareObjectsAccordingToSort(
+ BSON("a" << 1), BSON("a" << 2), BSON("b" << 1 << "a" << 1)),
+ 0);
+ ASSERT_EQ(
+ dps::compareObjectsAccordingToSort(BSON("a" << BSONNULL), BSON("b" << 1), BSON("a" << 1)),
+ 0);
+}
+
+TEST(DottedPathSupport, ExtractElementAtPath) {
+ BSONObj obj = BSON("a" << 1 << "b" << BSON("a" << 2) << "c"
+ << BSON_ARRAY(BSON("a" << 3) << BSON("a" << 4)));
+ ASSERT_EQUALS(1, dps::extractElementAtPath(obj, "a").numberInt());
+ ASSERT_EQUALS(2, dps::extractElementAtPath(obj, "b.a").numberInt());
+ ASSERT_EQUALS(3, dps::extractElementAtPath(obj, "c.0.a").numberInt());
+ ASSERT_EQUALS(4, dps::extractElementAtPath(obj, "c.1.a").numberInt());
+
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "x").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "a.x").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "x.y").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, ".").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "..").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "...").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "a.").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, ".a").eoo());
+ ASSERT_TRUE(dps::extractElementAtPath(obj, "b.a.").eoo());
+}
+
+TEST(DottedPathSupport, ExtractElementsBasedOnTemplate) {
+ BSONObj obj = BSON("a" << 10 << "b" << 11);
+
+ ASSERT_EQ(BSON("a" << 10).woCompare(dps::extractElementsBasedOnTemplate(obj, BSON("a" << 1))),
+ 0);
+ ASSERT_EQ(BSON("b" << 11).woCompare(dps::extractElementsBasedOnTemplate(obj, BSON("b" << 1))),
+ 0);
+ ASSERT_EQ(obj.woCompare(dps::extractElementsBasedOnTemplate(obj, BSON("a" << 1 << "b" << 1))),
+ 0);
+
+ ASSERT_EQ(dps::extractElementsBasedOnTemplate(obj, BSON("a" << 1 << "c" << 1))
+ .firstElement()
+ .fieldNameStringData(),
+ "a");
+}
+
+void dumpBSONElementSet(const BSONElementSet& elements, StringBuilder* sb) {
+ *sb << "[ ";
+ bool firstIteration = true;
+ for (auto&& elem : elements) {
+ if (!firstIteration) {
+ *sb << ", ";
+ }
+ *sb << "'" << elem << "'";
+ firstIteration = false;
+ }
+ *sb << " ]";
+}
+
+void assertBSONElementSetsAreEqual(const std::vector<BSONObj>& expectedObjs,
+ const BSONElementSet& actualElements) {
+ BSONElementSet expectedElements;
+ for (auto&& obj : expectedObjs) {
+ expectedElements.insert(obj.firstElement());
+ }
+
+ if (expectedElements.size() != actualElements.size()) {
+ StringBuilder sb;
+ sb << "Expected set to contain " << expectedElements.size()
+ << " element(s), but actual set contains " << actualElements.size()
+ << " element(s); Expected set: ";
+ dumpBSONElementSet(expectedElements, &sb);
+ sb << ", Actual set: ";
+ dumpBSONElementSet(actualElements, &sb);
+ FAIL(sb.str());
+ }
+
+ // We do our own comparison of the two BSONElementSets because BSONElement::operator== considers
+ // the field name.
+ auto expectedIt = expectedElements.begin();
+ auto actualIt = actualElements.begin();
+
+ for (size_t i = 0; i < expectedElements.size(); ++i) {
+ if (!expectedIt->valuesEqual(*actualIt)) {
+ StringBuilder sb;
+ sb << "Element '" << *expectedIt << "' doesn't have the same value as element '"
+ << *actualIt << "'; Expected set: ";
+ dumpBSONElementSet(expectedElements, &sb);
+ sb << ", Actual set: ";
+ dumpBSONElementSet(actualElements, &sb);
+ FAIL(sb.str());
+ }
+
+ ++expectedIt;
+ ++actualIt;
+ }
+}
+
+TEST(ExtractAllElementsAlongPath, NestedObjectWithScalarValue) {
+ BSONObj obj = BSON("a" << BSON("b" << 1));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = true;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual({BSON("" << 1)}, actualElements);
+}
+
+TEST(ExtractAllElementsAlongPath, NestedObjectWithEmptyArrayValue) {
+ BSONObj obj = BSON("a" << BSON("b" << BSONArrayBuilder().arr()));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = true;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual(std::vector<BSONObj>{}, actualElements);
+}
+
+TEST(ExtractAllElementsAlongPath, NestedObjectWithSingletonArrayValue) {
+ BSONObj obj = BSON("a" << BSON("b" << BSON_ARRAY(1)));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = true;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual({BSON("" << 1)}, actualElements);
+}
+
+TEST(ExtractAllElementsAlongPath, NestedObjectWithArrayValue) {
+ BSONObj obj = BSON("a" << BSON("b" << BSON_ARRAY(1 << 2 << 3)));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = true;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual({BSON("" << 1), BSON("" << 2), BSON("" << 3)}, actualElements);
+}
+
+TEST(ExtractAllElementsAlongPath, ObjectWithArrayOfSubobjectsWithScalarValue) {
+ BSONObj obj = BSON("a" << BSON_ARRAY(BSON("b" << 1) << BSON("b" << 2) << BSON("b" << 3)));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = true;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual({BSON("" << 1), BSON("" << 2), BSON("" << 3)}, actualElements);
+}
+
+TEST(ExtractAllElementsAlongPath, ObjectWithArrayOfSubobjectsWithArrayValues) {
+ BSONObj obj =
+ BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(1 << 2)) << BSON("b" << BSON_ARRAY(2 << 3))
+ << BSON("b" << BSON_ARRAY(3 << 1))));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = true;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual({BSON("" << 1), BSON("" << 2), BSON("" << 3)}, actualElements);
+}
+
+TEST(ExtractAllElementsAlongPath,
+ ObjectWithArrayOfSubobjectsWithArrayValuesButNotExpandingTrailingArrayValues) {
+ BSONObj obj = BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(1)) << BSON("b" << BSON_ARRAY(2))
+ << BSON("b" << BSON_ARRAY(3))));
+
+ BSONElementSet actualElements;
+ const bool expandArrayOnTrailingField = false;
+ dps::extractAllElementsAlongPath(obj, "a.b", actualElements, expandArrayOnTrailingField);
+
+ assertBSONElementSetsAreEqual(
+ {BSON("" << BSON_ARRAY(1)), BSON("" << BSON_ARRAY(2)), BSON("" << BSON_ARRAY(3))},
+ actualElements);
+}
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index a280f059f23..c173f950b8a 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/client.h"
@@ -61,6 +62,8 @@ using std::unique_ptr;
using std::string;
using std::stringstream;
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
const char kKeyField[] = "key";
@@ -223,7 +226,7 @@ public:
// available to us without this. If a collection scan is providing the data, we may
// have to expand an array.
BSONElementSet elts;
- obj.getFieldsDotted(key, elts);
+ dps::extractAllElementsAlongPath(obj, key, elts);
for (BSONElementSet::iterator it = elts.begin(); it != elts.end(); ++it) {
BSONElement elt = *it;
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index a55d60d0fb0..80d17229d5f 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -37,6 +37,7 @@
#include "mongo/client/connpool.h"
#include "mongo/client/parallel.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/collection_catalog_entry.h"
#include "mongo/db/catalog/database_holder.h"
@@ -91,6 +92,8 @@ using std::stringstream;
using std::unique_ptr;
using std::vector;
+namespace dps = ::mongo::dotted_path_support;
+
namespace mr {
AtomicUInt32 Config::JOB_NUMBER;
@@ -1090,7 +1093,7 @@ void State::finalReduce(OperationContext* txn, CurOp* curOp, ProgressMeterHolder
o = o.getOwned(); // we will be accessing outside of the lock
pm.hit();
- if (o.woSortOrder(prev, sortKey) == 0) {
+ if (dps::compareObjectsAccordingToSort(o, prev, sortKey) == 0) {
// object is same as previous, add to array
all.push_back(o);
if (pm->hits() % 100 == 0) {
@@ -1799,7 +1802,7 @@ public:
continue;
}
- if (t.woSortOrder(*(values.begin()), sortKey) == 0) {
+ if (dps::compareObjectsAccordingToSort(t, *(values.begin()), sortKey) == 0) {
values.push_back(t);
continue;
}
diff --git a/src/mongo/db/exec/SConscript b/src/mongo/db/exec/SConscript
index 7c224d4efbf..3be2ce04e17 100644
--- a/src/mongo/db/exec/SConscript
+++ b/src/mongo/db/exec/SConscript
@@ -10,6 +10,7 @@ env.Library(
],
LIBDEPS = [
"$BUILD_DIR/mongo/base",
+ "$BUILD_DIR/mongo/db/bson/dotted_path_support",
"$BUILD_DIR/mongo/db/service_context",
],
)
@@ -83,6 +84,7 @@ env.Library(
"scoped_timer",
"working_set",
"$BUILD_DIR/mongo/base",
+ "$BUILD_DIR/mongo/db/bson/dotted_path_support",
"$BUILD_DIR/mongo/db/concurrency/write_conflict_exception",
"$BUILD_DIR/mongo/db/commands",
"$BUILD_DIR/mongo/db/curop",
diff --git a/src/mongo/db/exec/geo_near.cpp b/src/mongo/db/exec/geo_near.cpp
index c53573706f0..fa1974ae6d0 100644
--- a/src/mongo/db/exec/geo_near.cpp
+++ b/src/mongo/db/exec/geo_near.cpp
@@ -35,6 +35,7 @@
#include "third_party/s2/s2regionintersection.h"
#include "mongo/base/owned_pointer_vector.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/exec/fetch.h"
#include "mongo/db/exec/index_scan.h"
#include "mongo/db/exec/working_set_computed_data.h"
@@ -54,6 +55,8 @@ namespace mongo {
using std::abs;
using std::unique_ptr;
+namespace dps = ::mongo::dotted_path_support;
+
//
// Shared GeoNear search functionality
//
@@ -100,7 +103,7 @@ static void extractGeometries(const BSONObj& doc,
BSONElementSet geomElements;
// NOTE: Annoyingly, we cannot just expand arrays b/c single 2d points are arrays, we need
// to manually expand all results to check if they are geometries
- doc.getFieldsDotted(path, geomElements, false /* expand arrays */);
+ dps::extractAllElementsAlongPath(doc, path, geomElements, false /* expand arrays */);
for (BSONElementSet::iterator it = geomElements.begin(); it != geomElements.end(); ++it) {
const BSONElement& el = *it;
diff --git a/src/mongo/db/exec/group.cpp b/src/mongo/db/exec/group.cpp
index 19729bbacf9..ccd2cea6991 100644
--- a/src/mongo/db/exec/group.cpp
+++ b/src/mongo/db/exec/group.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/exec/group.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/client_basic.h"
#include "mongo/db/exec/scoped_timer.h"
@@ -43,6 +44,8 @@ using std::unique_ptr;
using std::vector;
using stdx::make_unique;
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
// Helper function that extracts the group key from a BSONObj.
@@ -64,7 +67,7 @@ Status getKey(
*key = s->getObject("__returnValue");
return Status::OK();
}
- *key = obj.extractFields(keyPattern, true).getOwned();
+ *key = dps::extractElementsBasedOnTemplate(obj, keyPattern, true).getOwned();
return Status::OK();
}
diff --git a/src/mongo/db/exec/update.cpp b/src/mongo/db/exec/update.cpp
index 7fca4f3906b..c45f49cd5f7 100644
--- a/src/mongo/db/exec/update.cpp
+++ b/src/mongo/db/exec/update.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/exec/update.h"
#include "mongo/bson/mutable/algorithm.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/exec/scoped_timer.h"
#include "mongo/db/exec/working_set_common.h"
@@ -54,6 +55,7 @@ using std::vector;
using stdx::make_unique;
namespace mb = mutablebson;
+namespace dps = ::mongo::dotted_path_support;
namespace {
@@ -351,7 +353,7 @@ inline Status validate(const BSONObj& original,
}
} else {
// Find the potentially affected field in the original document.
- const BSONElement oldElem = original.getFieldDotted(current.dottedField());
+ const BSONElement oldElem = dps::extractElementAtPath(original, current.dottedField());
const BSONElement oldIdElem = original.getField(idFieldName);
// Ensure no arrays since neither _id nor shard keys can be in an array, or one.
diff --git a/src/mongo/db/exec/working_set.cpp b/src/mongo/db/exec/working_set.cpp
index 96b5c0ca360..6e8efc34e59 100644
--- a/src/mongo/db/exec/working_set.cpp
+++ b/src/mongo/db/exec/working_set.cpp
@@ -28,6 +28,7 @@
#include "mongo/db/exec/working_set.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/record_fetcher.h"
@@ -36,6 +37,8 @@ namespace mongo {
using std::string;
+namespace dps = ::mongo::dotted_path_support;
+
WorkingSet::MemberHolder::MemberHolder() : member(NULL) {}
WorkingSet::MemberHolder::~MemberHolder() {}
@@ -205,7 +208,7 @@ bool WorkingSetMember::hasFetcher() const {
bool WorkingSetMember::getFieldDotted(const string& field, BSONElement* out) const {
// If our state is such that we have an object, use it.
if (hasObj()) {
- *out = obj.value().getFieldDotted(field);
+ *out = dps::extractElementAtPath(obj.value(), field);
return true;
}
diff --git a/src/mongo/db/fts/SConscript b/src/mongo/db/fts/SConscript
index 307d7752112..9a58088d035 100644
--- a/src/mongo/db/fts/SConscript
+++ b/src/mongo/db/fts/SConscript
@@ -51,6 +51,7 @@ baseEnv.Library('base', [
'stop_words_list.cpp',
'tokenizer.cpp',
], LIBDEPS=["$BUILD_DIR/mongo/base",
+ "$BUILD_DIR/mongo/db/bson/dotted_path_support",
"$BUILD_DIR/mongo/db/common",
"$BUILD_DIR/mongo/db/fts/unicode/unicode",
"$BUILD_DIR/mongo/platform/platform",
diff --git a/src/mongo/db/fts/fts_index_format.cpp b/src/mongo/db/fts/fts_index_format.cpp
index c9698d59c93..222b54aa2a0 100644
--- a/src/mongo/db/fts/fts_index_format.cpp
+++ b/src/mongo/db/fts/fts_index_format.cpp
@@ -33,6 +33,7 @@
#include <third_party/murmurhash3/MurmurHash3.h>
#include "mongo/base/init.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/fts/fts_index_format.h"
#include "mongo/db/fts/fts_spec.h"
#include "mongo/util/hex.h"
@@ -46,6 +47,8 @@ namespace fts {
using std::string;
using std::vector;
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
BSONObj nullObj;
BSONElement nullElt;
@@ -115,7 +118,7 @@ void FTSIndexFormat::getKeys(const FTSSpec& spec, const BSONObj& obj, BSONObjSet
// compute the non FTS key elements
for (unsigned i = 0; i < spec.numExtraBefore(); i++) {
- BSONElement e = obj.getFieldDotted(spec.extraBefore(i));
+ BSONElement e = dps::extractElementAtPath(obj, spec.extraBefore(i));
if (e.eoo())
e = nullElt;
uassert(16675, "cannot have a multi-key as a prefix to a text index", e.type() != Array);
@@ -123,7 +126,7 @@ void FTSIndexFormat::getKeys(const FTSSpec& spec, const BSONObj& obj, BSONObjSet
extraSize += e.size();
}
for (unsigned i = 0; i < spec.numExtraAfter(); i++) {
- BSONElement e = obj.getFieldDotted(spec.extraAfter(i));
+ BSONElement e = dps::extractElementAtPath(obj, spec.extraAfter(i));
if (e.eoo())
e = nullElt;
extrasAfter.push_back(e);
diff --git a/src/mongo/db/fts/fts_spec.cpp b/src/mongo/db/fts/fts_spec.cpp
index 0c03ed8aa18..c9216b0bb45 100644
--- a/src/mongo/db/fts/fts_spec.cpp
+++ b/src/mongo/db/fts/fts_spec.cpp
@@ -31,6 +31,7 @@
#include "mongo/db/fts/fts_spec.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/field_ref.h"
#include "mongo/db/fts/fts_element_iterator.h"
#include "mongo/db/fts/fts_tokenizer.h"
@@ -45,6 +46,7 @@ namespace fts {
using std::map;
using std::string;
using namespace mongoutils;
+namespace dps = ::mongo::dotted_path_support;
const double DEFAULT_WEIGHT = 1;
const double MAX_WEIGHT = 1000000000;
@@ -242,7 +244,7 @@ Status FTSSpec::getIndexPrefix(const BSONObj& query, BSONObj* out) const {
BSONObjBuilder b;
for (unsigned i = 0; i < numExtraBefore(); i++) {
- BSONElement e = query.getFieldDotted(extraBefore(i));
+ BSONElement e = dps::extractElementAtPath(query, extraBefore(i));
if (e.eoo())
return Status(ErrorCodes::BadValue,
str::stream() << "need have an equality filter on: " << extraBefore(i));
diff --git a/src/mongo/db/fts/fts_spec_legacy.cpp b/src/mongo/db/fts/fts_spec_legacy.cpp
index f660c00f526..df34990953a 100644
--- a/src/mongo/db/fts/fts_spec_legacy.cpp
+++ b/src/mongo/db/fts/fts_spec_legacy.cpp
@@ -28,6 +28,7 @@
#include "mongo/db/fts/fts_spec.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/stringutils.h"
@@ -44,6 +45,8 @@ using std::map;
using std::string;
using namespace mongoutils;
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
void _addFTSStuff(BSONObjBuilder* b) {
b->append("_fts", INDEX_NAME);
@@ -170,7 +173,7 @@ void FTSSpec::_scoreDocumentV1(const BSONObj& obj, TermFrequencyMap* term_freqs)
for (Weights::const_iterator i = _weights.begin(); i != _weights.end(); i++) {
const char* leftOverName = i->first.c_str();
// name of field
- BSONElement e = obj.getFieldDottedOrArray(leftOverName);
+ BSONElement e = dps::extractElementAtPath(obj, leftOverName);
// weight associated to name of field
double weight = i->second;
@@ -181,7 +184,7 @@ void FTSSpec::_scoreDocumentV1(const BSONObj& obj, TermFrequencyMap* term_freqs)
while (j.more()) {
BSONElement x = j.next();
if (leftOverName[0] && x.isABSONObj())
- x = x.Obj().getFieldDotted(leftOverName);
+ x = dps::extractElementAtPath(x.Obj(), leftOverName);
if (x.type() == String)
_scoreStringV1(tools, x.valuestr(), term_freqs, weight);
}
diff --git a/src/mongo/db/geo/SConscript b/src/mongo/db/geo/SConscript
index 9c8e13d1268..ca2d94c7349 100644
--- a/src/mongo/db/geo/SConscript
+++ b/src/mongo/db/geo/SConscript
@@ -16,6 +16,7 @@ env.Library("geoparser", [ "geoparser.cpp",
"geometry_container.cpp" ],
LIBDEPS = [ "geometry",
"$BUILD_DIR/mongo/base",
+ "$BUILD_DIR/mongo/db/bson/dotted_path_support",
"$BUILD_DIR/third_party/s2/s2" ])
env.CppUnitTest("hash_test", [ "hash_test.cpp" ],
diff --git a/src/mongo/db/geo/geoparser.cpp b/src/mongo/db/geo/geoparser.cpp
index 7e58a768aa8..2be29d1dd7a 100644
--- a/src/mongo/db/geo/geoparser.cpp
+++ b/src/mongo/db/geo/geoparser.cpp
@@ -34,6 +34,7 @@
#include <string>
#include <vector>
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/geo/shapes.h"
#include "mongo/db/jsobj.h"
#include "mongo/util/log.h"
@@ -47,6 +48,8 @@ namespace mongo {
using std::unique_ptr;
using std::stringstream;
+namespace dps = ::mongo::dotted_path_support;
+
// This field must be present, and...
static const string GEOJSON_TYPE = "type";
// Have one of these values:
@@ -525,7 +528,7 @@ Status GeoParser::parseMultiPoint(const BSONObj& obj, MultiPointWithCRS* out) {
return status;
out->points.clear();
- BSONElement coordElt = obj.getFieldDotted(GEOJSON_COORDINATES);
+ BSONElement coordElt = dps::extractElementAtPath(obj, GEOJSON_COORDINATES);
status = parseArrayOfCoordinates(coordElt, &out->points);
if (!status.isOK())
return status;
@@ -546,7 +549,7 @@ Status GeoParser::parseMultiLine(const BSONObj& obj, bool skipValidation, MultiL
if (!status.isOK())
return status;
- BSONElement coordElt = obj.getFieldDotted(GEOJSON_COORDINATES);
+ BSONElement coordElt = dps::extractElementAtPath(obj, GEOJSON_COORDINATES);
if (Array != coordElt.type())
return BAD_VALUE("MultiLineString coordinates must be an array");
@@ -576,7 +579,7 @@ Status GeoParser::parseMultiPolygon(const BSONObj& obj,
if (!status.isOK())
return status;
- BSONElement coordElt = obj.getFieldDotted(GEOJSON_COORDINATES);
+ BSONElement coordElt = dps::extractElementAtPath(obj, GEOJSON_COORDINATES);
if (Array != coordElt.type())
return BAD_VALUE("MultiPolygon coordinates must be an array");
@@ -668,7 +671,7 @@ Status GeoParser::parseCenterSphere(const BSONObj& obj, CapWithCRS* out) {
Status GeoParser::parseGeometryCollection(const BSONObj& obj,
bool skipValidation,
GeometryCollection* out) {
- BSONElement coordElt = obj.getFieldDotted(GEOJSON_GEOMETRIES);
+ BSONElement coordElt = dps::extractElementAtPath(obj, GEOJSON_GEOMETRIES);
if (Array != coordElt.type())
return BAD_VALUE("GeometryCollection geometries must be an array");
@@ -780,7 +783,7 @@ GeoParser::GeoSpecifier GeoParser::parseGeoSpecifier(const BSONElement& type) {
}
GeoParser::GeoJSONType GeoParser::parseGeoJSONType(const BSONObj& obj) {
- BSONElement type = obj.getFieldDotted(GEOJSON_TYPE);
+ BSONElement type = dps::extractElementAtPath(obj, GEOJSON_TYPE);
if (String != type.type()) {
return GeoParser::GEOJSON_UNKNOWN;
}
diff --git a/src/mongo/db/index/SConscript b/src/mongo/db/index/SConscript
index 97fba307203..0f3556424d8 100644
--- a/src/mongo/db/index/SConscript
+++ b/src/mongo/db/index/SConscript
@@ -21,6 +21,7 @@ env.Library(
LIBDEPS=[
'expression_params',
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/fts/base',
'$BUILD_DIR/mongo/db/geo/geoparser',
'$BUILD_DIR/mongo/db/index_names',
diff --git a/src/mongo/db/index/btree_key_generator.cpp b/src/mongo/db/index/btree_key_generator.cpp
index 5e847e77438..ed80b1f1be4 100644
--- a/src/mongo/db/index/btree_key_generator.cpp
+++ b/src/mongo/db/index/btree_key_generator.cpp
@@ -31,6 +31,7 @@
#include <boost/optional.hpp>
#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/field_ref.h"
#include "mongo/db/query/collation/collation_index_key.h"
#include "mongo/db/query/collation/collator_interface.h"
@@ -38,6 +39,8 @@
namespace mongo {
+namespace dps = ::mongo::dotted_path_support;
+
// SortStage checks for this error code in order to informatively error when we try to sort keys
// with parallel arrays.
const int BtreeKeyGenerator::ParallelArraysCode = 10088;
@@ -114,7 +117,7 @@ void BtreeKeyGeneratorV0::getKeysImpl(std::vector<const char*> fieldNames,
if (*fieldNames[i] == '\0')
continue;
- BSONElement e = obj.getFieldDottedOrArray(fieldNames[i]);
+ BSONElement e = dps::extractElementAtPathOrArrayAlongPath(obj, fieldNames[i]);
if (e.eoo()) {
e = nullElt; // no matching field
@@ -251,7 +254,7 @@ BSONElement BtreeKeyGeneratorV1::extractNextElement(const BSONObj& obj,
*arrayNestedArray = false;
if (haveObjField) {
- return obj.getFieldDottedOrArray(*field);
+ return dps::extractElementAtPathOrArrayAlongPath(obj, *field);
} else if (positionalInfo.hasPositionallyIndexedElt()) {
if (arrField.type() == Array) {
*arrayNestedArray = true;
@@ -436,10 +439,10 @@ void BtreeKeyGeneratorV1::getKeysImplWithArray(
continue;
}
- // The earlier call to BSONObj::getFieldDottedOrArray(fieldNames[i]) modified
- // fieldNames[i] to refer to the suffix of the path immediately following the 'arrElt'
- // array value. If we haven't reached the end of this indexed field yet, then we must
- // have traversed through 'arrElt'.
+ // The earlier call to dps::extractElementAtPathOrArrayAlongPath(..., fieldNames[i])
+ // modified fieldNames[i] to refer to the suffix of the path immediately following the
+ // 'arrElt' array value. If we haven't reached the end of this indexed field yet, then
+ // we must have traversed through 'arrElt'.
invariant(fieldIsArray);
StringData part = fieldNames[i];
@@ -479,8 +482,8 @@ void BtreeKeyGeneratorV1::getKeysImplWithArray(
// multikey.
subPositionalInfo[i].arrayObj = arrObj;
subPositionalInfo[i].remainingPath = fieldNames[i];
- subPositionalInfo[i].dottedElt =
- arrObj.getFieldDottedOrArray(subPositionalInfo[i].remainingPath);
+ subPositionalInfo[i].dottedElt = dps::extractElementAtPathOrArrayAlongPath(
+ arrObj, subPositionalInfo[i].remainingPath);
}
// Generate a key for each element of the indexed array.
diff --git a/src/mongo/db/index/btree_key_generator.h b/src/mongo/db/index/btree_key_generator.h
index 7d33001a594..f6579593076 100644
--- a/src/mongo/db/index/btree_key_generator.h
+++ b/src/mongo/db/index/btree_key_generator.h
@@ -138,7 +138,7 @@ private:
// If we find a positionally indexed element, we traverse the remainder of the path
// until we find either another array element or the end of the path. The result of
- // this traversal (implemented using getFieldDottedOrArray()), is stored here and used
+ // this traversal (implemented using extractAllElementsAlongPath()), is stored here and used
// during the recursive call for each array element.
//
// Example:
@@ -146,7 +146,7 @@ private:
// generating keys is {a: [0, {b: [{c: 99}]}]}. We will find that {b: [{c: 99}]}
// is a positionally indexed element and store it as 'positionallyIndexedElt'.
//
- // We then call getFieldDottedOrArray() to traverse the remainder of the path,
+ // We then call extractAllElementsAlongPath() to traverse the remainder of the path,
// "b.1.c". The result is the array [{c: 99}] which is stored here as 'dottedElt'.
BSONElement dottedElt;
@@ -191,7 +191,7 @@ private:
MultikeyPaths* multikeyPaths) const;
/**
* A call to getKeysImplWithArray() begins by calling this for each field in the key
- * pattern. It uses getFieldDottedOrArray() to traverse the path '*field' in 'obj'.
+ * pattern. It uses extractAllElementsAlongPath() to traverse the path '*field' in 'obj'.
*
* The 'positionalInfo' arg is used for handling a field path where 'obj' has an
* array indexed by position. See the comments for PositionalPathInfo for more detail.
diff --git a/src/mongo/db/index/expression_keys_private.cpp b/src/mongo/db/index/expression_keys_private.cpp
index 9afc653127f..e44c950758a 100644
--- a/src/mongo/db/index/expression_keys_private.cpp
+++ b/src/mongo/db/index/expression_keys_private.cpp
@@ -32,6 +32,7 @@
#include <utility>
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/fts/fts_index_format.h"
#include "mongo/db/geo/geoconstants.h"
#include "mongo/db/geo/geometry_container.h"
@@ -51,6 +52,8 @@ namespace {
using namespace mongo;
+namespace dps = ::mongo::dotted_path_support;
+
//
// Helper functions for getHaystackKeys
//
@@ -220,7 +223,7 @@ void ExpressionKeysPrivate::get2DKeys(const BSONObj& obj,
// Get all the nested location fields, but don't return individual elements from
// the last array, if it exists.
- obj.getFieldsDotted(params.geo.c_str(), bSet, false);
+ dps::extractAllElementsAlongPath(obj, params.geo.c_str(), bSet, false);
if (bSet.empty())
return;
@@ -289,7 +292,7 @@ void ExpressionKeysPrivate::get2DKeys(const BSONObj& obj,
++i) {
// Get *all* fields for the index key
BSONElementSet eSet;
- obj.getFieldsDotted(i->first, eSet);
+ dps::extractAllElementsAlongPath(obj, i->first, eSet);
if (eSet.size() == 0)
b.appendNull("");
@@ -329,7 +332,7 @@ void ExpressionKeysPrivate::getHashKeys(const BSONObj& obj,
const CollatorInterface* collator,
BSONObjSet* keys) {
const char* cstr = hashedField.c_str();
- BSONElement fieldVal = obj.getFieldDottedOrArray(cstr);
+ BSONElement fieldVal = dps::extractElementAtPath(obj, cstr);
// Convert strings to comparison keys.
BSONObj fieldValObj;
@@ -365,7 +368,7 @@ void ExpressionKeysPrivate::getHaystackKeys(const BSONObj& obj,
const std::vector<std::string>& otherFields,
double bucketSize,
BSONObjSet* keys) {
- BSONElement loc = obj.getFieldDotted(geoField);
+ BSONElement loc = dps::extractElementAtPath(obj, geoField);
if (loc.eoo()) {
return;
@@ -390,9 +393,8 @@ void ExpressionKeysPrivate::getHaystackKeys(const BSONObj& obj,
BSONElementSet all;
- // This is getFieldsDotted (plural not singular) since the object we're indexing
- // may be an array.
- obj.getFieldsDotted(otherFields[0], all);
+ // The object we're indexing may be an array.
+ dps::extractAllElementsAlongPath(obj, otherFields[0], all);
if (all.size() == 0) {
// We're indexing a document that doesn't have the secondary non-geo field present.
@@ -444,7 +446,7 @@ void ExpressionKeysPrivate::getS2Keys(const BSONObj& obj,
// the value of the field, or they're transformed if the field is geo.
BSONElementSet fieldElements;
// false means Don't expand the last array, duh.
- obj.getFieldsDotted(e.fieldName(), fieldElements, false);
+ dps::extractAllElementsAlongPath(obj, e.fieldName(), fieldElements, false);
BSONObjSet keysForThisField;
if (IndexNames::GEO_2DSPHERE == e.valuestr()) {
diff --git a/src/mongo/db/index/haystack_access_method.cpp b/src/mongo/db/index/haystack_access_method.cpp
index d6a50fdac88..64b699332e3 100644
--- a/src/mongo/db/index/haystack_access_method.cpp
+++ b/src/mongo/db/index/haystack_access_method.cpp
@@ -34,6 +34,7 @@
#include "mongo/base/status.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/geo/hash.h"
#include "mongo/db/index/expression_keys_private.h"
@@ -47,6 +48,8 @@ namespace mongo {
using std::unique_ptr;
+namespace dps = ::mongo::dotted_path_support;
+
HaystackAccessMethod::HaystackAccessMethod(IndexCatalogEntry* btreeState,
SortedDataInterface* btree)
: IndexAccessMethod(btreeState, btree) {
@@ -95,7 +98,7 @@ void HaystackAccessMethod::searchCommand(OperationContext* txn,
for (unsigned i = 0; i < _otherFields.size(); i++) {
// See if the non-geo field we're indexing on is in the provided search term.
- BSONElement e = search.getFieldDotted(_otherFields[i]);
+ BSONElement e = dps::extractElementAtPath(search, _otherFields[i]);
if (e.eoo())
bb.appendNull("");
else
diff --git a/src/mongo/db/index/haystack_access_method_internal.h b/src/mongo/db/index/haystack_access_method_internal.h
index 0ab511f42e4..4bc2e7430ad 100644
--- a/src/mongo/db/index/haystack_access_method_internal.h
+++ b/src/mongo/db/index/haystack_access_method_internal.h
@@ -30,11 +30,14 @@
#include <vector>
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/geo/shapes.h"
#include "mongo/db/record_id.h"
namespace mongo {
+namespace dps = ::mongo::dotted_path_support;
+
class GeoHaystackSearchHopper {
public:
/**
@@ -63,7 +66,7 @@ public:
void consider(const RecordId& loc) {
if (limitReached())
return;
- Point p(_collection->docFor(_txn, loc).value().getFieldDotted(_geoField));
+ Point p(dps::extractElementAtPath(_collection->docFor(_txn, loc).value(), _geoField));
if (distance(_near, p) > _maxDistance)
return;
_locs.push_back(loc);
diff --git a/src/mongo/db/ops/SConscript b/src/mongo/db/ops/SConscript
index ab345cb238c..5b468f1c858 100644
--- a/src/mongo/db/ops/SConscript
+++ b/src/mongo/db/ops/SConscript
@@ -70,6 +70,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/matcher/expressions',
'$BUILD_DIR/mongo/db/global_timestamp',
'update_common',
diff --git a/src/mongo/db/ops/modifier_push_sorter.h b/src/mongo/db/ops/modifier_push_sorter.h
index 6d795ec372d..6b9d150198e 100644
--- a/src/mongo/db/ops/modifier_push_sorter.h
+++ b/src/mongo/db/ops/modifier_push_sorter.h
@@ -30,6 +30,7 @@
#include "mongo/bson/mutable/document.h"
#include "mongo/bson/mutable/element.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/jsobj.h"
namespace mongo {
@@ -46,6 +47,7 @@ struct PatternElementCmp {
: sortPattern(pattern), useWholeValue(pattern.hasField("")) {}
bool operator()(const mutablebson::Element& lhs, const mutablebson::Element& rhs) const {
+ namespace dps = ::mongo::dotted_path_support;
if (useWholeValue) {
const int comparedValue = lhs.compareWithElement(rhs, false);
@@ -59,8 +61,8 @@ struct PatternElementCmp {
BSONObj rhsObj =
rhs.getType() == Object ? rhs.getValueObject() : rhs.getValue().wrap("");
- BSONObj lhsKey = lhsObj.extractFields(sortPattern, true);
- BSONObj rhsKey = rhsObj.extractFields(sortPattern, true);
+ BSONObj lhsKey = dps::extractElementsBasedOnTemplate(lhsObj, sortPattern, true);
+ BSONObj rhsKey = dps::extractElementsBasedOnTemplate(rhsObj, sortPattern, true);
return lhsKey.woCompare(rhsKey, sortPattern) < 0;
}
diff --git a/src/mongo/db/ops/modifier_push_test.cpp b/src/mongo/db/ops/modifier_push_test.cpp
index 6e37fc24d74..a50e06022a0 100644
--- a/src/mongo/db/ops/modifier_push_test.cpp
+++ b/src/mongo/db/ops/modifier_push_test.cpp
@@ -39,6 +39,7 @@
#include "mongo/bson/mutable/document.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
#include "mongo/bson/ordering.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/ops/log_builder.h"
@@ -65,6 +66,8 @@ using mongo::mutablebson::Element;
using std::sort;
using std::vector;
+namespace dps = ::mongo::dotted_path_support;
+
void combineVec(const vector<int>& origVec,
const vector<int>& modVec,
int32_t slice,
@@ -113,8 +116,8 @@ struct ProjectKeyCmp {
if (useWholeValue) {
ret = left.woCompare(right, Ordering::make(sortPattern), false);
} else {
- BSONObj lhsKey = left.extractFields(sortPattern, true);
- BSONObj rhsKey = right.extractFields(sortPattern, true);
+ BSONObj lhsKey = dps::extractElementsBasedOnTemplate(left, sortPattern, true);
+ BSONObj rhsKey = dps::extractElementsBasedOnTemplate(right, sortPattern, true);
ret = lhsKey.woCompare(rhsKey, sortPattern);
}
return ret < 0;
diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript
index 898e8d0738a..eef0b7ecada 100644
--- a/src/mongo/db/pipeline/SConscript
+++ b/src/mongo/db/pipeline/SConscript
@@ -126,6 +126,7 @@ docSourceEnv.Library(
'document_value',
'expression',
'$BUILD_DIR/mongo/client/clientdriver',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/matcher/expressions',
'$BUILD_DIR/mongo/db/matcher/expression_algo',
'$BUILD_DIR/mongo/db/service_context',
@@ -152,6 +153,7 @@ env.Library(
'document_value',
'$BUILD_DIR/mongo/db/auth/authorization_manager_global',
'$BUILD_DIR/mongo/db/auth/authcore',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/query/collation/collation_serializer',
'$BUILD_DIR/mongo/db/query/collation/collator_factory_interface',
'$BUILD_DIR/mongo/db/repl/read_concern_args',
diff --git a/src/mongo/db/pipeline/document.h b/src/mongo/db/pipeline/document.h
index e7584b13ade..840c81315f0 100644
--- a/src/mongo/db/pipeline/document.h
+++ b/src/mongo/db/pipeline/document.h
@@ -99,7 +99,7 @@ public:
return storage().getField(pos).val;
}
- /** Similar to BSONObj::getFieldDotted, but using FieldPath rather than a dotted string.
+ /** Similar to extractAllElementsAlongPath(), but using FieldPath rather than a dotted string.
* If you pass a non-NULL positions vector, you get back a path suitable
* to pass to MutableDocument::setNestedField.
*
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
index 3c5fccf47bd..7f0e4548d66 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
@@ -31,6 +31,7 @@
#include "document_source.h"
#include "mongo/base/init.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/pipeline/document.h"
#include "mongo/db/pipeline/expression.h"
@@ -43,6 +44,8 @@ namespace mongo {
using boost::intrusive_ptr;
using std::unique_ptr;
+namespace dps = ::mongo::dotted_path_support;
+
REGISTER_DOCUMENT_SOURCE(graphLookup, DocumentSourceGraphLookUp::createFromBson);
const char* DocumentSourceGraphLookUp::getSourceName() const {
@@ -220,7 +223,7 @@ bool DocumentSourceGraphLookUp::addToVisitedAndFrontier(BSONObj result, long lon
// array, we treat it as connecting to multiple values, so we must add each element to
// '_frontier'.
BSONElementSet recurseOnValues;
- result.getFieldsDotted(_connectFromField.getPath(false), recurseOnValues);
+ dps::extractAllElementsAlongPath(result, _connectFromField.getPath(false), recurseOnValues);
for (auto&& elem : recurseOnValues) {
Value recurseOn = Value(elem);
@@ -243,7 +246,7 @@ bool DocumentSourceGraphLookUp::addToVisitedAndFrontier(BSONObj result, long lon
void DocumentSourceGraphLookUp::addToCache(const BSONObj& result,
const unordered_set<Value, Value::Hash>& queried) {
BSONElementSet cacheByValues;
- result.getFieldsDotted(_connectToField.getPath(false), cacheByValues);
+ dps::extractAllElementsAlongPath(result, _connectToField.getPath(false), cacheByValues);
for (auto&& elem : cacheByValues) {
Value cacheBy(elem);
diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp
index 9f5d6e1fd67..c1ad28bc375 100644
--- a/src/mongo/db/pipeline/pipeline.cpp
+++ b/src/mongo/db/pipeline/pipeline.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
@@ -57,6 +58,8 @@ using std::ostringstream;
using std::string;
using std::vector;
+namespace dps = ::mongo::dotted_path_support;
+
const char Pipeline::commandName[] = "aggregate";
const char Pipeline::pipelineName[] = "pipeline";
const char Pipeline::collationName[] = "collation";
@@ -234,7 +237,7 @@ Status Pipeline::checkAuthForCommand(ClientBasic* client,
std::vector<Privilege> privileges;
- if (cmdObj.getFieldDotted("pipeline.0.$indexStats")) {
+ if (dps::extractElementAtPath(cmdObj, "pipeline.0.$indexStats")) {
Privilege::addPrivilegeToPrivilegeVector(
&privileges,
Privilege(ResourcePattern::forAnyNormalResource(), ActionType::indexStats));
diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript
index c588986617a..676f27d3cd5 100644
--- a/src/mongo/db/query/SConscript
+++ b/src/mongo/db/query/SConscript
@@ -29,6 +29,7 @@ env.Library(
],
LIBDEPS=[
"$BUILD_DIR/mongo/base",
+ "$BUILD_DIR/mongo/db/bson/dotted_path_support",
"$BUILD_DIR/mongo/db/index/expression_params",
"$BUILD_DIR/mongo/db/index_names",
"$BUILD_DIR/mongo/db/matcher/expression_algo",
diff --git a/src/mongo/db/query/planner_access.cpp b/src/mongo/db/query/planner_access.cpp
index c3172d5387d..349a25b99f7 100644
--- a/src/mongo/db/query/planner_access.cpp
+++ b/src/mongo/db/query/planner_access.cpp
@@ -36,6 +36,7 @@
#include <vector>
#include "mongo/base/owned_pointer_vector.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/matcher/expression_array.h"
#include "mongo/db/matcher/expression_geo.h"
#include "mongo/db/matcher/expression_text.h"
@@ -52,6 +53,8 @@ namespace {
using namespace mongo;
+namespace dps = ::mongo::dotted_path_support;
+
/**
* Text node functors.
*/
@@ -125,7 +128,7 @@ QuerySolutionNode* QueryPlannerAccess::makeCollectionScan(const CanonicalQuery&
// If the hint is {$natural: +-1} this changes the direction of the collection scan.
if (!query.getParsed().getHint().isEmpty()) {
- BSONElement natural = query.getParsed().getHint().getFieldDotted("$natural");
+ BSONElement natural = dps::extractElementAtPath(query.getParsed().getHint(), "$natural");
if (!natural.eoo()) {
csn->direction = natural.numberInt() >= 0 ? 1 : -1;
}
@@ -135,7 +138,7 @@ QuerySolutionNode* QueryPlannerAccess::makeCollectionScan(const CanonicalQuery&
// direction if both are specified.
const BSONObj& sortObj = query.getParsed().getSort();
if (!sortObj.isEmpty()) {
- BSONElement natural = sortObj.getFieldDotted("$natural");
+ BSONElement natural = dps::extractElementAtPath(sortObj, "$natural");
if (!natural.eoo()) {
csn->direction = natural.numberInt() >= 0 ? 1 : -1;
}
diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp
index 1a507d16ef2..e7ab375b03c 100644
--- a/src/mongo/db/query/planner_analysis.cpp
+++ b/src/mongo/db/query/planner_analysis.cpp
@@ -33,6 +33,7 @@
#include <set>
#include <vector>
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/index/expression_params.h"
#include "mongo/db/index/s2_common.h"
#include "mongo/db/jsobj.h"
@@ -48,6 +49,8 @@ using std::endl;
using std::string;
using std::vector;
+namespace dps = ::mongo::dotted_path_support;
+
//
// Helpers for bounds explosion AKA quick-and-dirty SERVER-1205.
//
@@ -472,7 +475,7 @@ QuerySolutionNode* QueryPlannerAnalysis::analyzeSort(const CanonicalQuery& query
// If the sort is $natural, we ignore it, assuming that the caller has detected that and
// outputted a collscan to satisfy the desired order.
- BSONElement natural = sortObj.getFieldDotted("$natural");
+ BSONElement natural = dps::extractElementAtPath(sortObj, "$natural");
if (!natural.eoo()) {
return solnRoot;
}
diff --git a/src/mongo/db/query/query_planner.cpp b/src/mongo/db/query/query_planner.cpp
index 2b76ac930f9..49905949142 100644
--- a/src/mongo/db/query/query_planner.cpp
+++ b/src/mongo/db/query/query_planner.cpp
@@ -35,6 +35,7 @@
#include <vector>
#include "mongo/client/dbclientinterface.h" // For QueryOption_foobar
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/matcher/expression_algo.h"
#include "mongo/db/matcher/expression_geo.h"
#include "mongo/db/matcher/expression_text.h"
@@ -53,6 +54,8 @@ namespace mongo {
using std::unique_ptr;
using std::numeric_limits;
+namespace dps = ::mongo::dotted_path_support;
+
// Copied verbatim from db/index.h
static bool isIdIndex(const BSONObj& pattern) {
BSONObjIterator i(pattern);
@@ -460,8 +463,8 @@ Status QueryPlanner::plan(const CanonicalQuery& query,
if (!query.getParsed().getHint().isEmpty() || !query.getParsed().getSort().isEmpty()) {
BSONObj hintObj = query.getParsed().getHint();
BSONObj sortObj = query.getParsed().getSort();
- BSONElement naturalHint = hintObj.getFieldDotted("$natural");
- BSONElement naturalSort = sortObj.getFieldDotted("$natural");
+ BSONElement naturalHint = dps::extractElementAtPath(hintObj, "$natural");
+ BSONElement naturalSort = dps::extractElementAtPath(sortObj, "$natural");
// A hint overrides a $natural sort. This means that we don't force a table
// scan if there is a $natural sort with a non-$natural hint.
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index 8f5bd5759bc..2fecf3aeb24 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -127,6 +127,7 @@ env.CppUnitTest(
],
LIBDEPS=[
'replication_executor_test_fixture',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/unittest/concurrency',
],
)
diff --git a/src/mongo/db/repl/replication_executor_test.cpp b/src/mongo/db/repl/replication_executor_test.cpp
index 7b2de1e1fe1..80378b2004b 100644
--- a/src/mongo/db/repl/replication_executor_test.cpp
+++ b/src/mongo/db/repl/replication_executor_test.cpp
@@ -31,6 +31,7 @@
#include <map>
#include "mongo/base/init.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/repl/replication_executor.h"
@@ -53,6 +54,8 @@ namespace {
using executor::NetworkInterfaceMock;
using unittest::assertGet;
+namespace dps = ::mongo::dotted_path_support;
+
const int64_t prngSeed = 1;
MONGO_INITIALIZER(ReplExecutorCommonTests)(InitializerContext*) {
@@ -175,12 +178,14 @@ TEST_F(ReplicationExecutorTest, CancelBeforeRunningFutureWork) {
});
ASSERT_OK(cbhWithStatus.getStatus());
- ASSERT_EQUALS(1, executor.getDiagnosticBSON().getFieldDotted("queues.sleepers").Int());
- ASSERT_EQUALS(0, executor.getDiagnosticBSON().getFieldDotted("queues.ready").Int());
+ ASSERT_EQUALS(1,
+ dps::extractElementAtPath(executor.getDiagnosticBSON(), "queues.sleepers").Int());
+ ASSERT_EQUALS(0, dps::extractElementAtPath(executor.getDiagnosticBSON(), "queues.ready").Int());
executor.cancel(cbhWithStatus.getValue());
- ASSERT_EQUALS(0, executor.getDiagnosticBSON().getFieldDotted("queues.sleepers").Int());
- ASSERT_EQUALS(1, executor.getDiagnosticBSON().getFieldDotted("queues.ready").Int());
+ ASSERT_EQUALS(0,
+ dps::extractElementAtPath(executor.getDiagnosticBSON(), "queues.sleepers").Int());
+ ASSERT_EQUALS(1, dps::extractElementAtPath(executor.getDiagnosticBSON(), "queues.ready").Int());
}
// Equivalent to EventChainAndWaitingTest::onGo
@@ -199,7 +204,7 @@ TEST_F(ReplicationExecutorTest, ScheduleCallbackOnFutureEvent) {
// Wait for a future event.
executor.onEvent(ping, fn);
- ASSERT_EQUALS(0, executor.getDiagnosticBSON().getFieldDotted("queues.ready").Int());
+ ASSERT_EQUALS(0, dps::extractElementAtPath(executor.getDiagnosticBSON(), "queues.ready").Int());
executor.signalEvent(ping);
executor.waitForEvent(pong);
}
diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript
index a7fec9d434a..812a0aa6ec5 100644
--- a/src/mongo/db/s/SConscript
+++ b/src/mongo/db/s/SConscript
@@ -92,6 +92,7 @@ env.Library(
'unset_sharding_command.cpp',
],
LIBDEPS=[
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/commands',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_global',
'$BUILD_DIR/mongo/s/serveronly',
diff --git a/src/mongo/db/s/check_sharding_index_command.cpp b/src/mongo/db/s/check_sharding_index_command.cpp
index 8f24954949b..afbb278e4f6 100644
--- a/src/mongo/db/s/check_sharding_index_command.cpp
+++ b/src/mongo/db/s/check_sharding_index_command.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/commands.h"
#include "mongo/db/db_raii.h"
#include "mongo/db/dbhelpers.h"
@@ -48,6 +49,8 @@ namespace mongo {
using std::string;
using std::unique_ptr;
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
class CheckShardingIndex : public Command {
@@ -178,7 +181,7 @@ public:
for (int x = 0; x <= k; x++)
real = j.next();
- real = obj.getFieldDotted(real.fieldName());
+ real = dps::extractElementAtPath(obj, real.fieldName());
if (real.type())
continue;
diff --git a/src/mongo/db/s/split_vector_command.cpp b/src/mongo/db/s/split_vector_command.cpp
index 9c4dccfac96..b6922737f96 100644
--- a/src/mongo/db/s/split_vector_command.cpp
+++ b/src/mongo/db/s/split_vector_command.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/commands.h"
#include "mongo/db/db_raii.h"
@@ -60,6 +61,8 @@ using std::string;
using std::stringstream;
using std::vector;
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
BSONObj prettyKey(const BSONObj& keyPattern, const BSONObj& key) {
@@ -269,8 +272,8 @@ public:
// to be removed at the end. If a key appears more times than entries allowed on a
// chunk, we issue a warning and split on the following key.
set<BSONObj> tooFrequentKeys;
- splitKeys.push_back(
- prettyKey(idx->keyPattern(), currKey.getOwned()).extractFields(keyPattern));
+ splitKeys.push_back(dps::extractElementsBasedOnTemplate(
+ prettyKey(idx->keyPattern(), currKey.getOwned()), keyPattern));
exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);
while (1) {
@@ -278,8 +281,8 @@ public:
currCount++;
if (currCount > keyCount && !forceMedianSplit) {
- currKey = prettyKey(idx->keyPattern(), currKey.getOwned())
- .extractFields(keyPattern);
+ currKey = dps::extractElementsBasedOnTemplate(
+ prettyKey(idx->keyPattern(), currKey.getOwned()), keyPattern);
// Do not use this split key if it is the same used in the previous split
// point.
if (currKey.woCompare(splitKeys.back()) == 0) {
diff --git a/src/mongo/db/storage/SConscript b/src/mongo/db/storage/SConscript
index c2b6ae9e5e4..4680e07f672 100644
--- a/src/mongo/db/storage/SConscript
+++ b/src/mongo/db/storage/SConscript
@@ -175,6 +175,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
]
)
diff --git a/src/mongo/db/storage/storage_engine_metadata.cpp b/src/mongo/db/storage/storage_engine_metadata.cpp
index 144ba7c838b..9b5c74ba2a5 100644
--- a/src/mongo/db/storage/storage_engine_metadata.cpp
+++ b/src/mongo/db/storage/storage_engine_metadata.cpp
@@ -40,6 +40,7 @@
#include <ostream>
#include <vector>
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/jsobj.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/log.h"
@@ -47,6 +48,8 @@
namespace mongo {
+namespace dps = ::mongo::dotted_path_support;
+
namespace {
const std::string kMetadataBasename = "storage.bson";
@@ -172,7 +175,7 @@ Status StorageEngineMetadata::read() {
}
// Validate 'storage.engine' field.
- BSONElement storageEngineElement = obj.getFieldDotted("storage.engine");
+ BSONElement storageEngineElement = dps::extractElementAtPath(obj, "storage.engine");
if (storageEngineElement.type() != mongo::String) {
return Status(ErrorCodes::FailedToParse,
str::stream() << "The 'storage.engine' field in metadata must be a string: "
@@ -188,7 +191,7 @@ Status StorageEngineMetadata::read() {
_storageEngine = storageEngine;
// Read storage engine options generated by storage engine factory from startup options.
- BSONElement storageEngineOptionsElement = obj.getFieldDotted("storage.options");
+ BSONElement storageEngineOptionsElement = dps::extractElementAtPath(obj, "storage.options");
if (!storageEngineOptionsElement.eoo()) {
if (!storageEngineOptionsElement.isABSONObj()) {
return Status(ErrorCodes::FailedToParse,
diff --git a/src/mongo/db/storage/wiredtiger/SConscript b/src/mongo/db/storage/wiredtiger/SConscript
index 20d170ac8a5..ca266e4ce74 100644
--- a/src/mongo/db/storage/wiredtiger/SConscript
+++ b/src/mongo/db/storage/wiredtiger/SConscript
@@ -41,11 +41,12 @@ if wiredtiger:
LIBDEPS= [
'storage_wiredtiger_customization_hooks',
'$BUILD_DIR/mongo/base',
- '$BUILD_DIR/mongo/db/namespace_string',
+ '$BUILD_DIR/mongo/db/bson/dotted_path_support',
'$BUILD_DIR/mongo/db/catalog/collection_options',
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
'$BUILD_DIR/mongo/db/concurrency/write_conflict_exception',
'$BUILD_DIR/mongo/db/index/index_descriptor',
+ '$BUILD_DIR/mongo/db/namespace_string',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/mongo/db/storage/index_entry_comparison',
'$BUILD_DIR/mongo/db/storage/journal_listener',
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp
index 02914421a15..8c51bf5689d 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_kv_engine.cpp
@@ -43,6 +43,7 @@
#include "mongo/base/error_codes.h"
#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/catalog/collection_catalog_entry.h"
#include "mongo/db/client.h"
#include "mongo/db/commands/server_status_metric.h"
@@ -78,6 +79,8 @@ namespace mongo {
using std::set;
using std::string;
+namespace dps = ::mongo::dotted_path_support;
+
class WiredTigerKVEngine::WiredTigerJournalFlusher : public BackgroundJob {
public:
explicit WiredTigerJournalFlusher(WiredTigerSessionCache* sessionCache)
@@ -509,8 +512,9 @@ Status WiredTigerKVEngine::createSortedDataInterface(OperationContext* opCtx,
if (!collOptions.indexOptionDefaults["storageEngine"].eoo()) {
BSONObj storageEngineOptions = collOptions.indexOptionDefaults["storageEngine"].Obj();
- collIndexOptions = storageEngineOptions.getFieldDotted(_canonicalName + ".configString")
- .valuestrsafe();
+ collIndexOptions =
+ dps::extractElementAtPath(storageEngineOptions, _canonicalName + ".configString")
+ .valuestrsafe();
}
}