summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp1
-rw-r--r--src/mongo/db/ops/SConscript1
-rw-r--r--src/mongo/db/ops/parsed_update.cpp1
-rw-r--r--src/mongo/db/ops/update_request.h13
-rw-r--r--src/mongo/db/ops/write_ops.idl6
-rw-r--r--src/mongo/db/ops/write_ops_exec.cpp1
-rw-r--r--src/mongo/db/query/SConscript22
-rw-r--r--src/mongo/db/query/count_command.idl7
-rw-r--r--src/mongo/db/query/count_request.cpp11
-rw-r--r--src/mongo/db/query/count_request.h6
-rw-r--r--src/mongo/db/query/get_executor.cpp44
-rw-r--r--src/mongo/db/query/hint.idl41
-rw-r--r--src/mongo/db/query/hint_parser.cpp53
-rw-r--r--src/mongo/db/query/hint_parser.h49
-rw-r--r--src/mongo/db/query/hint_parser_test.cpp76
-rw-r--r--src/mongo/idl/basic_types.idl1
-rw-r--r--src/mongo/shell/bulk_api.js15
-rw-r--r--src/mongo/shell/collection.js13
-rw-r--r--src/mongo/shell/explainable.js5
19 files changed, 321 insertions, 45 deletions
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index c2892e08fd9..1c63ac0756b 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -371,6 +371,7 @@ private:
updateRequest.setMulti(_batch.getUpdates()[0].getMulti());
updateRequest.setUpsert(_batch.getUpdates()[0].getUpsert());
updateRequest.setYieldPolicy(PlanExecutor::YIELD_AUTO);
+ updateRequest.setHint(_batch.getUpdates()[0].getHint());
updateRequest.setExplain();
const ExtensionsCallbackReal extensionsCallback(opCtx,
diff --git a/src/mongo/db/ops/SConscript b/src/mongo/db/ops/SConscript
index dff8b81dd47..6ca1e089132 100644
--- a/src/mongo/db/ops/SConscript
+++ b/src/mongo/db/ops/SConscript
@@ -37,6 +37,7 @@ env.Library(
'$BUILD_DIR/mongo/db/commands/test_commands_enabled',
'$BUILD_DIR/mongo/db/dbmessage',
'$BUILD_DIR/mongo/db/pipeline/runtime_constants_idl',
+ '$BUILD_DIR/mongo/db/query/hint_parser',
'$BUILD_DIR/mongo/idl/idl_parser',
],
)
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index 67215128ce0..07a44c54bd8 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -104,6 +104,7 @@ Status ParsedUpdate::parseQueryToCQ() {
qr->setSort(_request->getSort());
qr->setCollation(_request->getCollation());
qr->setExplain(_request->isExplain());
+ qr->setHint(_request->getHint());
// Limit should only used for the findAndModify command when a sort is specified. If a sort
// is requested, we want to use a top-k sort for efficiency reasons, so should pass the
diff --git a/src/mongo/db/ops/update_request.h b/src/mongo/db/ops/update_request.h
index ee30cc6a827..f946302c6b9 100644
--- a/src/mongo/db/ops/update_request.h
+++ b/src/mongo/db/ops/update_request.h
@@ -190,6 +190,14 @@ public:
_returnDocs = value;
}
+ void setHint(const BSONObj& hint) {
+ _hint = hint;
+ }
+
+ BSONObj getHint() const {
+ return _hint;
+ }
+
inline bool shouldReturnOldDocs() const {
return _returnDocs == ReturnDocOption::RETURN_OLD;
}
@@ -258,6 +266,11 @@ public:
private:
const NamespaceString& _nsString;
+ // The hint provided, if any. If the hint was by index key pattern, the value of '_hint' is
+ // the key pattern hinted. If the hint was by index name, the value of '_hint' is
+ // {$hint: <String>}, where <String> is the index name hinted.
+ BSONObj _hint;
+
// Contains the query that selects documents to update.
BSONObj _query;
diff --git a/src/mongo/db/ops/write_ops.idl b/src/mongo/db/ops/write_ops.idl
index a4ddaadd966..9409aa73041 100644
--- a/src/mongo/db/ops/write_ops.idl
+++ b/src/mongo/db/ops/write_ops.idl
@@ -34,6 +34,8 @@ global:
imports:
- "mongo/db/logical_session_id.idl"
- "mongo/db/pipeline/runtime_constants.idl"
+ - "mongo/idl/basic_types.idl"
+ - "mongo/db/query/hint.idl"
types:
multi_delete_bool:
@@ -110,6 +112,10 @@ structs:
description: "Specifies which array elements an update modifier should apply to."
type: array<object>
optional: true
+ hint:
+ description: "Specifies the hint to use for the operation."
+ type: indexHint
+ default: mongo::BSONObj()
multi:
description: "If true, updates all documents that meet the query criteria. If false,
limits the update to one document which meets the query criteria."
diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp
index 79b519779c8..13d303bdf95 100644
--- a/src/mongo/db/ops/write_ops_exec.cpp
+++ b/src/mongo/db/ops/write_ops_exec.cpp
@@ -715,6 +715,7 @@ static SingleWriteResult performSingleUpdateOpWithDupKeyRetry(OperationContext*
request.setArrayFilters(write_ops::arrayFiltersOf(op));
request.setMulti(op.getMulti());
request.setUpsert(op.getUpsert());
+ request.setHint(op.getHint());
auto readConcernArgs = repl::ReadConcernArgs::get(opCtx);
request.setYieldPolicy(readConcernArgs.getLevel() ==
diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript
index 0ae841ab6de..a2183a6f2fb 100644
--- a/src/mongo/db/query/SConscript
+++ b/src/mongo/db/query/SConscript
@@ -178,6 +178,7 @@ env.Library(
"$BUILD_DIR/mongo/idl/idl_parser",
'$BUILD_DIR/mongo/rpc/command_status',
'$BUILD_DIR/mongo/rpc/rpc',
+ '$BUILD_DIR/mongo/db/query/hint_parser',
'query_request',
]
)
@@ -261,6 +262,27 @@ env.Library(
],
)
+env.Library(
+ target="hint_parser",
+ source=[
+ "hint_parser.cpp",
+ env.Idlc('hint.idl')[0],
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ ],
+)
+
+env.CppUnitTest(
+ target="hint_parser_test",
+ source=[
+ "hint_parser_test.cpp"
+ ],
+ LIBDEPS=[
+ "hint_parser",
+ ],
+)
+
env.CppUnitTest(
target="canonical_query_test",
source=[
diff --git a/src/mongo/db/query/count_command.idl b/src/mongo/db/query/count_command.idl
index 2d7cf893f04..fc6eed0c1dc 100644
--- a/src/mongo/db/query/count_command.idl
+++ b/src/mongo/db/query/count_command.idl
@@ -33,14 +33,9 @@ global:
imports:
- "mongo/idl/basic_types.idl"
+ - "mongo/db/query/hint.idl"
types:
- indexHint:
- bson_serialization_type: any
- description: "Either a string index name or an object index specification."
- cpp_type: mongo::BSONObj
- deserializer: ::mongo::count_request::countParseHint
-
countLimit:
bson_serialization_type: any
description: "The absolute value of an int for limit."
diff --git a/src/mongo/db/query/count_request.cpp b/src/mongo/db/query/count_request.cpp
index 155580c226d..8d5b47370eb 100644
--- a/src/mongo/db/query/count_request.cpp
+++ b/src/mongo/db/query/count_request.cpp
@@ -60,17 +60,6 @@ long long countParseSkip(const BSONElement& element) {
return skip;
}
-BSONObj countParseHint(const BSONElement& element) {
- if (element.type() == BSONType::String) {
- return BSON("$hint" << element.valueStringData());
- } else if (element.type() == BSONType::Object) {
- return element.Obj();
- } else {
- uasserted(31012, "Hint must be a string or an object");
- }
- MONGO_UNREACHABLE;
-}
-
long long countParseMaxTime(const BSONElement& element) {
auto maxTimeVal = uassertStatusOK(QueryRequest::parseMaxTimeMS(element));
return static_cast<long long>(maxTimeVal);
diff --git a/src/mongo/db/query/count_request.h b/src/mongo/db/query/count_request.h
index 4680323152b..e80ec9a259c 100644
--- a/src/mongo/db/query/count_request.h
+++ b/src/mongo/db/query/count_request.h
@@ -48,12 +48,6 @@ long long countParseLimit(const BSONElement& element);
long long countParseSkip(const BSONElement& element);
/**
- * Parses a hint for a CountCommand. Returns the hint object, or if the element was a string the
- * string wrapped in an object of the form {"$hint": <index_name>}.
- */
-BSONObj countParseHint(const BSONElement& element);
-
-/**
* Parses a maxTimeMS for a CountCommand. Errors if the value passed is negative.
* Throws on invalid values.
*/
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index a9158d333fb..54ade9343eb 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -1035,27 +1035,31 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorUpdate(
driver->refreshIndexKeys(&updateIndexData);
if (!parsedUpdate->hasParsedQuery()) {
- // This is the idhack fast-path for getting a PlanExecutor without doing the work
- // to create a CanonicalQuery.
- const BSONObj& unparsedQuery = request->getQuery();
-
- const IndexDescriptor* descriptor = collection->getIndexCatalog()->findIdIndex(opCtx);
- const bool hasCollectionDefaultCollation = CollatorInterface::collatorsMatch(
- parsedUpdate->getCollator(), collection->getDefaultCollator());
-
- if (descriptor && CanonicalQuery::isSimpleIdQuery(unparsedQuery) &&
- request->getProj().isEmpty() && hasCollectionDefaultCollation) {
- LOG(2) << "Using idhack: " << redact(unparsedQuery);
-
- // Working set 'ws' is discarded. InternalPlanner::updateWithIdHack() makes its own
- // WorkingSet.
- return InternalPlanner::updateWithIdHack(opCtx,
- collection,
- updateStageParams,
- descriptor,
- unparsedQuery["_id"].wrap(),
- policy);
+ // Only consider using the idhack if no hint was provided.
+ if (request->getHint().isEmpty()) {
+ // This is the idhack fast-path for getting a PlanExecutor without doing the work
+ // to create a CanonicalQuery.
+ const BSONObj& unparsedQuery = request->getQuery();
+
+ const IndexDescriptor* descriptor = collection->getIndexCatalog()->findIdIndex(opCtx);
+
+ const bool hasCollectionDefaultCollation = CollatorInterface::collatorsMatch(
+ parsedUpdate->getCollator(), collection->getDefaultCollator());
+
+ if (descriptor && CanonicalQuery::isSimpleIdQuery(unparsedQuery) &&
+ request->getProj().isEmpty() && hasCollectionDefaultCollation) {
+ LOG(2) << "Using idhack: " << redact(unparsedQuery);
+
+ // Working set 'ws' is discarded. InternalPlanner::updateWithIdHack() makes its own
+ // WorkingSet.
+ return InternalPlanner::updateWithIdHack(opCtx,
+ collection,
+ updateStageParams,
+ descriptor,
+ unparsedQuery["_id"].wrap(),
+ policy);
+ }
}
// If we're here then we don't have a parsed query, but we're also not eligible for
diff --git a/src/mongo/db/query/hint.idl b/src/mongo/db/query/hint.idl
new file mode 100644
index 00000000000..869c3612241
--- /dev/null
+++ b/src/mongo/db/query/hint.idl
@@ -0,0 +1,41 @@
+# Copyright (C) 2019-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# 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
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# 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 Server Side 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.
+#
+
+# IDL type for index hints
+
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/db/query/hint_parser.h"
+types:
+ indexHint:
+ bson_serialization_type: any
+ description: "Either a string index name or an object index specification."
+ cpp_type: mongo::BSONObj
+ serializer: "::mongo::serializeHintToBSON"
+ deserializer: "::mongo::parseHint"
diff --git a/src/mongo/db/query/hint_parser.cpp b/src/mongo/db/query/hint_parser.cpp
new file mode 100644
index 00000000000..cdb321940bb
--- /dev/null
+++ b/src/mongo/db/query/hint_parser.cpp
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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/query/hint_parser.h"
+
+#include "mongo/bson/bsonobjbuilder.h"
+
+namespace mongo {
+
+BSONObj parseHint(const BSONElement& element) {
+ if (element.type() == BSONType::String) {
+ return BSON("$hint" << element.valueStringData());
+ } else if (element.type() == BSONType::Object) {
+ return element.Obj();
+ } else {
+ uasserted(ErrorCodes::FailedToParse, "Hint must be a string or an object");
+ }
+ MONGO_UNREACHABLE;
+}
+
+void serializeHintToBSON(const BSONObj& hint, StringData fieldName, BSONObjBuilder* builder) {
+ if (hint.isEmpty())
+ return;
+ builder->append(fieldName, hint);
+}
+
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/db/query/hint_parser.h b/src/mongo/db/query/hint_parser.h
new file mode 100644
index 00000000000..aee0e3a4126
--- /dev/null
+++ b/src/mongo/db/query/hint_parser.h
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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 "mongo/bson/bsonelement.h"
+#include "mongo/bson/bsonobj.h"
+
+namespace mongo {
+
+/**
+ * Parses a hint. Returns the hint object, or if the element was a string the
+ * string wrapped in an object of the form {"$hint": <index_name>}.
+ */
+BSONObj parseHint(const BSONElement& element);
+
+/**
+ * Writes the hint object if it is non-empty.
+ */
+void serializeHintToBSON(const BSONObj& hint, StringData fieldName, BSONObjBuilder* builder);
+
+} // namespace mongo
diff --git a/src/mongo/db/query/hint_parser_test.cpp b/src/mongo/db/query/hint_parser_test.cpp
new file mode 100644
index 00000000000..03b49102007
--- /dev/null
+++ b/src/mongo/db/query/hint_parser_test.cpp
@@ -0,0 +1,76 @@
+
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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/bson/bsonmisc.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/query/hint_parser.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+
+namespace {
+
+TEST(CommandParsers, ParseKeyPatternHint) {
+ auto hint = BSON("hint" << BSON("x" << 5));
+ ASSERT_BSONOBJ_EQ(parseHint(hint.firstElement()), BSON("x" << 5));
+}
+
+TEST(CommandParsers, ParseIndexNameHint) {
+ auto hint = BSON("hint"
+ << "x_1");
+ ASSERT_BSONOBJ_EQ(parseHint(hint.firstElement()),
+ BSON("$hint"
+ << "x_1"));
+}
+
+TEST(CommandParsers, BadHintType) {
+ auto hint = BSON("hint" << 1);
+ ASSERT_THROWS_CODE(
+ parseHint(hint.firstElement()), AssertionException, ErrorCodes::FailedToParse);
+}
+
+TEST(CommandParsers, SerializeNonEmptyHint) {
+ auto hint = BSON("x" << 1);
+ BSONObjBuilder bob;
+ serializeHintToBSON(hint, "hint", &bob);
+ ASSERT_BSONOBJ_EQ(bob.obj(), BSON("hint" << BSON("x" << 1)));
+}
+
+TEST(CommandParsers, ShouldNotSerializeEmptyHint) {
+ BSONObjBuilder bob;
+ serializeHintToBSON(BSONObj(), "hint", &bob);
+ ASSERT_FALSE(bob.obj().hasField("hint"));
+}
+} // namespace
+
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/idl/basic_types.idl b/src/mongo/idl/basic_types.idl
index 084ca20fe42..7005fdc4bc3 100644
--- a/src/mongo/idl/basic_types.idl
+++ b/src/mongo/idl/basic_types.idl
@@ -157,3 +157,4 @@ types:
cpp_type: "mongo::NamespaceString"
serializer: mongo::NamespaceString::toString
deserializer: mongo::NamespaceString
+
diff --git a/src/mongo/shell/bulk_api.js b/src/mongo/shell/bulk_api.js
index b18189636d1..eac31f7a871 100644
--- a/src/mongo/shell/bulk_api.js
+++ b/src/mongo/shell/bulk_api.js
@@ -668,6 +668,11 @@ var _bulk_api_module = (function() {
var document =
{q: currentOp.selector, u: updateDocument, multi: true, upsert: upsert};
+ // Copy over the hint, if we have one.
+ if (currentOp.hasOwnProperty('hint')) {
+ document.hint = currentOp.hint;
+ }
+
// Copy over the collation, if we have one.
if (currentOp.hasOwnProperty('collation')) {
document.collation = currentOp.collation;
@@ -691,6 +696,11 @@ var _bulk_api_module = (function() {
var document =
{q: currentOp.selector, u: updateDocument, multi: false, upsert: upsert};
+ // Copy over the hint, if we have one.
+ if (currentOp.hasOwnProperty('hint')) {
+ document.hint = currentOp.hint;
+ }
+
// Copy over the collation, if we have one.
if (currentOp.hasOwnProperty('collation')) {
document.collation = currentOp.collation;
@@ -721,6 +731,11 @@ var _bulk_api_module = (function() {
return findOperations;
},
+ hint: function(hint) {
+ currentOp.hint = hint;
+ return findOperations;
+ },
+
removeOne: function() {
// Establish the removeOne command
var document = {q: currentOp.selector, limit: 1};
diff --git a/src/mongo/shell/collection.js b/src/mongo/shell/collection.js
index 40a6cbd7cf5..64f079ef984 100644
--- a/src/mongo/shell/collection.js
+++ b/src/mongo/shell/collection.js
@@ -123,10 +123,10 @@ DBCollection.prototype.help = function() {
".update( query, <update object or pipeline>[, upsert_bool, multi_bool] ) - instead of two flags, you can pass an object with fields: upsert, multi");
print(
"\tdb." + shortName +
- ".updateOne( filter, <update object or pipeline>, <optional params> ) - update the first matching document, optional parameters are: upsert, w, wtimeout, j");
+ ".updateOne( filter, <update object or pipeline>, <optional params> ) - update the first matching document, optional parameters are: upsert, w, wtimeout, j, hint");
print(
"\tdb." + shortName +
- ".updateMany( filter, <update object or pipeline>, <optional params> ) - update all matching documents, optional parameters are: upsert, w, wtimeout, j");
+ ".updateMany( filter, <update object or pipeline>, <optional params> ) - update all matching documents, optional parameters are: upsert, w, wtimeout, j, hint");
print("\tdb." + shortName + ".validate( <full> ) - SLOW");
print("\tdb." + shortName + ".getShardVersion() - only for use with sharding");
print("\tdb." + shortName +
@@ -449,6 +449,8 @@ DBCollection.prototype._parseUpdate = function(query, updateSpec, upsert, multi)
var wc = undefined;
var collation = undefined;
var arrayFilters = undefined;
+ let hint = undefined;
+
// can pass options via object for improved readability
if (typeof(upsert) === "object") {
if (multi) {
@@ -462,6 +464,7 @@ DBCollection.prototype._parseUpdate = function(query, updateSpec, upsert, multi)
upsert = opts.upsert;
collation = opts.collation;
arrayFilters = opts.arrayFilters;
+ hint = opts.hint;
}
// Normalize 'upsert' and 'multi' to booleans.
@@ -475,6 +478,7 @@ DBCollection.prototype._parseUpdate = function(query, updateSpec, upsert, multi)
return {
"query": query,
"updateSpec": updateSpec,
+ "hint": hint,
"upsert": upsert,
"multi": multi,
"wc": wc,
@@ -489,6 +493,7 @@ DBCollection.prototype.update = function(query, updateSpec, upsert, multi) {
var parsed = this._parseUpdate(query, updateSpec, upsert, multi);
var query = parsed.query;
var updateSpec = parsed.updateSpec;
+ const hint = parsed.hint;
var upsert = parsed.upsert;
var multi = parsed.multi;
var wc = parsed.wc;
@@ -503,6 +508,10 @@ DBCollection.prototype.update = function(query, updateSpec, upsert, multi) {
var bulk = this.initializeOrderedBulkOp();
var updateOp = bulk.find(query);
+ if (hint) {
+ updateOp.hint(hint);
+ }
+
if (upsert) {
updateOp = updateOp.upsert();
}
diff --git a/src/mongo/shell/explainable.js b/src/mongo/shell/explainable.js
index 5f898a40103..637d19d2bf7 100644
--- a/src/mongo/shell/explainable.js
+++ b/src/mongo/shell/explainable.js
@@ -191,10 +191,15 @@ var Explainable = (function() {
var multi = parsed.multi;
var collation = parsed.collation;
var arrayFilters = parsed.arrayFilters;
+ var hint = parsed.hint;
var bulk = this._collection.initializeOrderedBulkOp();
var updateOp = bulk.find(query);
+ if (hint) {
+ updateOp.hint(hint);
+ }
+
if (upsert) {
updateOp = updateOp.upsert();
}