summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r--src/mongo/db/pipeline/document_source_lookup.cpp2
-rw-r--r--src/mongo/db/pipeline/expression.cpp6
-rw-r--r--src/mongo/db/pipeline/expression_context.cpp13
-rw-r--r--src/mongo/db/pipeline/expression_context.h41
4 files changed, 59 insertions, 3 deletions
diff --git a/src/mongo/db/pipeline/document_source_lookup.cpp b/src/mongo/db/pipeline/document_source_lookup.cpp
index 7eb2f9d7169..496c641b969 100644
--- a/src/mongo/db/pipeline/document_source_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_lookup.cpp
@@ -674,8 +674,10 @@ void DocumentSourceLookUp::resolveLetVariables(const Document& localDoc, Variabl
void DocumentSourceLookUp::initializeResolvedIntrospectionPipeline() {
copyVariablesToExpCtx(_variables, _variablesParseState, _fromExpCtx.get());
+ _fromExpCtx->startExpressionCounters();
_resolvedIntrospectionPipeline =
Pipeline::parse(_resolvedPipeline, _fromExpCtx, lookupPipeValidator);
+ _fromExpCtx->stopExpressionCounters();
}
void DocumentSourceLookUp::serializeToArray(
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp
index 7b53cd77eeb..c63c5fde288 100644
--- a/src/mongo/db/pipeline/expression.cpp
+++ b/src/mongo/db/pipeline/expression.cpp
@@ -46,6 +46,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/pipeline/expression_context.h"
#include "mongo/db/query/datetime/date_time_support.h"
+#include "mongo/db/stats/counters.h"
#include "mongo/platform/bits.h"
#include "mongo/platform/decimal128.h"
#include "mongo/util/regex_util.h"
@@ -123,6 +124,8 @@ void Expression::registerExpression(
str::stream() << "Duplicate expression (" << key << ") registered.",
op == parserMap.end());
parserMap[key] = {parser, requiredMinVersion};
+ // Add this expression to the global map of operator counters for expressions.
+ operatorCountersAggExpressions.addAggExpressionCounter(key);
}
intrusive_ptr<Expression> Expression::parseExpression(
@@ -155,6 +158,9 @@ intrusive_ptr<Expression> Expression::parseExpression(
<< " for more information.",
!expCtx->maxFeatureCompatibilityVersion || !entry.requiredMinVersion ||
(*entry.requiredMinVersion <= *expCtx->maxFeatureCompatibilityVersion));
+
+ // Increment the counter for this expression in the current context.
+ expCtx->incrementAggExprCounter(opName);
return entry.parser(expCtx, obj.firstElement(), vps);
}
diff --git a/src/mongo/db/pipeline/expression_context.cpp b/src/mongo/db/pipeline/expression_context.cpp
index 5bfc56283f7..26c9854160f 100644
--- a/src/mongo/db/pipeline/expression_context.cpp
+++ b/src/mongo/db/pipeline/expression_context.cpp
@@ -215,21 +215,28 @@ intrusive_ptr<ExpressionContext> ExpressionContext::copyWith(
}
void ExpressionContext::startExpressionCounters() {
- if (!_expressionCounters) {
+ if (enabledCounters && !_expressionCounters) {
_expressionCounters = boost::make_optional<ExpressionCounters>({});
}
}
void ExpressionContext::incrementMatchExprCounter(StringData name) {
- if (_expressionCounters) {
+ if (enabledCounters && _expressionCounters) {
++_expressionCounters.get().matchExprCountersMap[name];
}
}
+void ExpressionContext::incrementAggExprCounter(StringData name) {
+ if (enabledCounters && _expressionCounters) {
+ ++_expressionCounters.get().aggExprCountersMap[name];
+ }
+}
+
void ExpressionContext::stopExpressionCounters() {
- if (_expressionCounters) {
+ if (enabledCounters && _expressionCounters) {
operatorCountersMatchExpressions.mergeCounters(
_expressionCounters.get().matchExprCountersMap);
+ operatorCountersAggExpressions.mergeCounters(_expressionCounters.get().aggExprCountersMap);
}
_expressionCounters = boost::none;
}
diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h
index 341bc4317cb..8ab69171792 100644
--- a/src/mongo/db/pipeline/expression_context.h
+++ b/src/mongo/db/pipeline/expression_context.h
@@ -110,6 +110,15 @@ public:
};
/**
+ * The structure ExpressionCounters encapsulates counters for match, aggregate, and other
+ * expression types as seen in end-user queries.
+ */
+ struct ExpressionCounters {
+ StringMap<uint64_t> aggExprCountersMap;
+ StringMap<uint64_t> matchExprCountersMap;
+ };
+
+ /**
* Constructs an ExpressionContext to be used for Pipeline parsing and evaluation.
* 'resolvedNamespaces' maps collection names (not full namespaces) to ResolvedNamespaces.
*/
@@ -316,11 +325,20 @@ public:
void incrementMatchExprCounter(StringData name);
/**
+ * Increment the counter for the aggregate expression with a given name.
+ */
+ void incrementAggExprCounter(StringData name);
+
+ /**
* Merge expression counters from the current expression context into the global maps
* and stop counting.
*/
void stopExpressionCounters();
+ bool expressionCountersAreActive() {
+ return _expressionCounters.is_initialized();
+ }
+
// The explain verbosity requested by the user, or boost::none if no explain was requested.
boost::optional<ExplainOptions::Verbosity> explain;
@@ -390,6 +408,29 @@ public:
// True if this ExpressionContext is used to parse a collection validator expression.
bool isParsingCollectionValidator = false;
+ // Indicates where there is any chance this operation will be profiled. Must be set at
+ // construction.
+ const bool mayDbProfile = true;
+
+ // These fields can be used in a context when API version validations were not enforced during
+ // parse time (Example creating a view or validator), but needs to be enforce while querying
+ // later.
+ bool exprUnstableForApiV1 = false;
+ bool exprDeprectedForApiV1 = false;
+
+ // Tracks whether the collator to use for the aggregation matches the default collation of the
+ // collection or view. For collectionless aggregates this is set to 'kNoDefaultCollation'.
+ enum class CollationMatchesDefault { kNoDefault, kYes, kNo };
+ CollationMatchesDefault collationMatchesDefault = CollationMatchesDefault::kNoDefault;
+
+ // When non-empty, contains the unmodified user provided aggregation command.
+ BSONObj originalAggregateCommand;
+
+ // True if the expression context is the original one for a given pipeline.
+ // False if another context is created for the same pipeline. Used to disable duplicate
+ // expression counting.
+ bool enabledCounters = true;
+
protected:
static const int kInterruptCheckPeriod = 128;