/** * Copyright (C) 2018-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 * . * * 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 #include #include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/query/explain_options.h" namespace mongo { template class StatusWith; class Document; /** * Represents the user-supplied options to the aggregate command. */ class AggregationRequest { public: static constexpr StringData kCommandName = "aggregate"_sd; static constexpr StringData kCursorName = "cursor"_sd; static constexpr StringData kBatchSizeName = "batchSize"_sd; static constexpr StringData kFromMongosName = "fromMongos"_sd; static constexpr StringData kNeedsMergeName = "needsMerge"_sd; static constexpr StringData kNeedsMerge34Name = "fromRouter"_sd; static constexpr StringData kPipelineName = "pipeline"_sd; static constexpr StringData kCollationName = "collation"_sd; static constexpr StringData kExplainName = "explain"_sd; static constexpr StringData kAllowDiskUseName = "allowDiskUse"_sd; static constexpr StringData kHintName = "hint"_sd; static constexpr StringData kCommentName = "comment"_sd; static constexpr long long kDefaultBatchSize = 101; /** * Parse an aggregation pipeline definition from 'pipelineElem'. Returns a non-OK status if * pipeline is not an array or if any of the array elements are not objects. */ static StatusWith> parsePipelineFromBSON(BSONElement pipelineElem); /** * Create a new instance of AggregationRequest by parsing the raw command object. Returns a * non-OK status if a required field was missing, if there was an unrecognized field name or if * there was a bad value for one of the fields. * * If we are parsing a request for an explained aggregation with an explain verbosity provided, * then 'explainVerbosity' contains this information. In this case, 'cmdObj' may not itself * contain the explain specifier. Otherwise, 'explainVerbosity' should be boost::none. */ static StatusWith parseFromBSON( NamespaceString nss, const BSONObj& cmdObj, boost::optional explainVerbosity = boost::none); /** * Convenience overload which constructs the request's NamespaceString from the given database * name and command object. */ static StatusWith parseFromBSON( const std::string& dbName, const BSONObj& cmdObj, boost::optional explainVerbosity = boost::none); /* * The first field in 'cmdObj' must be a string representing a valid collection name, or the * number 1. In the latter case, returns a reserved namespace that does not represent a user * collection. See 'NamespaceString::makeCollectionlessAggregateNSS()'. */ static NamespaceString parseNs(const std::string& dbname, const BSONObj& cmdObj); /** * Constructs an AggregationRequest over the given namespace with the given pipeline. All * options aside from the pipeline assume their default values. */ AggregationRequest(NamespaceString nss, std::vector pipeline); /** * Serializes the options to a Document. Note that this serialization includes the original * pipeline object, as specified. Callers will likely want to override this field with a * serialization of a parsed and optimized Pipeline object. * * The explain option is not serialized. Since the explain command format is {explain: * {aggregate: ...}, ...}, explain options are not part of the aggregate command object. */ Document serializeToCommandObj() const; // // Getters. // long long getBatchSize() const { return _batchSize; } const NamespaceString& getNamespaceString() const { return _nss; } /** * An unparsed version of the pipeline. All BSONObjs are owned. */ const std::vector& getPipeline() const { return _pipeline; } /** * Returns true if this request originated from a mongoS. */ bool isFromMongos() const { return _fromMongos; } /** * Returns true if this request originated from a 3.4 mongos. */ bool isFrom34Mongos() const { return _from34Mongos; } /** * Returns true if this request represents the shards part of a split pipeline, and should * produce mergeable output. */ bool needsMerge() const { return _needsMerge; } bool shouldAllowDiskUse() const { return _allowDiskUse; } bool shouldBypassDocumentValidation() const { return _bypassDocumentValidation; } /** * Returns an empty object if no collation was specified. */ BSONObj getCollation() const { return _collation; } BSONObj getHint() const { return _hint; } const std::string& getComment() const { return _comment; } boost::optional getExplain() const { return _explainMode; } unsigned int getMaxTimeMS() const { return _maxTimeMS; } const BSONObj& getReadConcern() const { return _readConcern; } const BSONObj& getUnwrappedReadPref() const { return _unwrappedReadPref; } // // Setters for optional fields. // /** * Negative batchSize is illegal but batchSize of 0 is allowed. */ void setBatchSize(long long batchSize) { uassert(40203, "batchSize must be non-negative", batchSize >= 0); _batchSize = batchSize; } void setCollation(BSONObj collation) { _collation = collation.getOwned(); } void setHint(BSONObj hint) { _hint = hint.getOwned(); } void setComment(const std::string& comment) { _comment = comment; } void setExplain(boost::optional verbosity) { _explainMode = verbosity; } void setAllowDiskUse(bool allowDiskUse) { _allowDiskUse = allowDiskUse; } void setFromMongos(bool isFromMongos) { _fromMongos = isFromMongos; } void setFrom34Mongos(bool isFrom34Mongos) { _from34Mongos = isFrom34Mongos; } void setNeedsMerge(bool needsMerge) { _needsMerge = needsMerge; } void setBypassDocumentValidation(bool shouldBypassDocumentValidation) { _bypassDocumentValidation = shouldBypassDocumentValidation; } void setMaxTimeMS(unsigned int maxTimeMS) { _maxTimeMS = maxTimeMS; } void setReadConcern(BSONObj readConcern) { _readConcern = readConcern.getOwned(); } void setUnwrappedReadPref(BSONObj unwrappedReadPref) { _unwrappedReadPref = unwrappedReadPref.getOwned(); } private: // Required fields. const NamespaceString _nss; // An unparsed version of the pipeline. const std::vector _pipeline; long long _batchSize; // Optional fields. // An owned copy of the user-specified collation object, or an empty object if no collation was // specified. BSONObj _collation; // 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: }, where is the index name hinted. BSONObj _hint; // The comment parameter attached to this aggregation, empty if not set. std::string _comment; BSONObj _readConcern; // The unwrapped readPreference object, if one was given to us by the mongos command processor. // This object will be empty when no readPreference is specified or if the request does not // originate from mongos. BSONObj _unwrappedReadPref; // The explain mode to use, or boost::none if this is not a request for an aggregation explain. boost::optional _explainMode; bool _allowDiskUse = false; bool _fromMongos = false; bool _needsMerge = false; bool _bypassDocumentValidation = false; // We track whether the aggregation request came from a 3.4 mongos. If so, the merge may occur // on a 3.4 shard (which does not understand sort key metadata), and we should not serialize the // sort key. // TODO SERVER-30924: remove this. bool _from34Mongos = false; // A user-specified maxTimeMS limit, or a value of '0' if not specified. unsigned int _maxTimeMS = 0; }; } // namespace mongo