diff options
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/ops/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/ops/parsed_update.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/ops/update_request.h | 13 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops.idl | 6 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_exec.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/query/SConscript | 22 | ||||
-rw-r--r-- | src/mongo/db/query/count_command.idl | 7 | ||||
-rw-r--r-- | src/mongo/db/query/count_request.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/query/count_request.h | 6 | ||||
-rw-r--r-- | src/mongo/db/query/get_executor.cpp | 44 | ||||
-rw-r--r-- | src/mongo/db/query/hint.idl | 41 | ||||
-rw-r--r-- | src/mongo/db/query/hint_parser.cpp | 53 | ||||
-rw-r--r-- | src/mongo/db/query/hint_parser.h | 49 | ||||
-rw-r--r-- | src/mongo/db/query/hint_parser_test.cpp | 76 | ||||
-rw-r--r-- | src/mongo/idl/basic_types.idl | 1 | ||||
-rw-r--r-- | src/mongo/shell/bulk_api.js | 15 | ||||
-rw-r--r-- | src/mongo/shell/collection.js | 13 | ||||
-rw-r--r-- | src/mongo/shell/explainable.js | 5 |
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(); } |