summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Murphy <benjamin_murphy@me.com>2016-01-27 16:42:04 -0500
committerBenjamin Murphy <benjamin_murphy@me.com>2016-02-08 12:53:48 -0500
commitc3a232ef38480f317cd42cc00755fd9032c107d2 (patch)
treebb664b92f2ffcf1b6c9c1dab0ad483404ac7d813
parenta1a4f91a9c70b3f9f58f2922c260f1df97418e2c (diff)
downloadmongo-c3a232ef38480f317cd42cc00755fd9032c107d2.tar.gz
SERVER-19643 Aggregation directly from a shard does not use sharding filter.
-rw-r--r--jstests/aggregation/testshard1.js11
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp2
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp23
-rw-r--r--src/mongo/db/pipeline/pipeline_d.h3
4 files changed, 34 insertions, 5 deletions
diff --git a/jstests/aggregation/testshard1.js b/jstests/aggregation/testshard1.js
index 64cc46ffaa6..ef9f91bae70 100644
--- a/jstests/aggregation/testshard1.js
+++ b/jstests/aggregation/testshard1.js
@@ -1,4 +1,5 @@
load('jstests/aggregation/extras/utils.js');
+load('jstests/libs/analyze_plan.js'); // For planHasStage.
// Use this for aggregations that only have arrays or results of specified order.
// It will check that cursors return the same results as non-cursors.
@@ -267,6 +268,16 @@ for (var shardName in res.shards) {
}
(function() {
+ jsTestLog("Do a sharded explain from a mongod, not mongos, to ensure that it does not have " +
+ "a SHARDING_FILTER stage.");
+ var shardDb = shardedAggTest.shard0.getDB('aggShard');
+ var res = shardDb.ts1.aggregate([{$match: {}}], {explain: true});
+ printjson(res);
+ assert.commandWorked(res);
+ assert(!planHasStage(res.stages[0].$cursor.queryPlanner.winningPlan, "SHARDING_FILTER"));
+}());
+
+(function() {
jsTestLog('Testing a $match stage on the shard key.');
var outCollection = 'testShardKeyMatchOut';
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index fc3537d1a49..31b80d4fda6 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -224,7 +224,7 @@ public:
// This does mongod-specific stuff like creating the input PlanExecutor and adding
// it to the front of the pipeline if needed.
std::shared_ptr<PlanExecutor> input =
- PipelineD::prepareCursorSource(txn, collection, pPipeline, pCtx);
+ PipelineD::prepareCursorSource(txn, collection, nss, pPipeline, pCtx);
pPipeline->stitch();
if (collection && input) {
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index 06114c90404..4cebf691c26 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -214,6 +214,7 @@ StatusWith<std::unique_ptr<PlanExecutor>> attemptToGetExecutor(
shared_ptr<PlanExecutor> PipelineD::prepareCursorSource(
OperationContext* txn,
Collection* collection,
+ const NamespaceString& nss,
const intrusive_ptr<Pipeline>& pPipeline,
const intrusive_ptr<ExpressionContext>& pExpCtx) {
// We will be modifying the source vector as we go.
@@ -292,8 +293,16 @@ shared_ptr<PlanExecutor> PipelineD::prepareCursorSource(
}
// Create the PlanExecutor.
- auto exec = prepareExecutor(
- txn, collection, pPipeline, pExpCtx, sortStage, deps, queryObj, &sortObj, &projForQuery);
+ auto exec = prepareExecutor(txn,
+ collection,
+ nss,
+ pPipeline,
+ pExpCtx,
+ sortStage,
+ deps,
+ queryObj,
+ &sortObj,
+ &projForQuery);
return addCursorSource(pPipeline, pExpCtx, exec, deps, queryObj, sortObj, projForQuery);
}
@@ -301,6 +310,7 @@ shared_ptr<PlanExecutor> PipelineD::prepareCursorSource(
std::shared_ptr<PlanExecutor> PipelineD::prepareExecutor(
OperationContext* txn,
Collection* collection,
+ const NamespaceString& nss,
const intrusive_ptr<Pipeline>& pipeline,
const intrusive_ptr<ExpressionContext>& expCtx,
const intrusive_ptr<DocumentSourceSort>& sortStage,
@@ -326,8 +336,13 @@ std::shared_ptr<PlanExecutor> PipelineD::prepareExecutor(
//
// LATER - We should attempt to determine if the results from the query are returned in some
// order so we can then apply other optimizations there are tickets for, such as SERVER-4507.
- size_t plannerOpts = QueryPlannerParams::DEFAULT | QueryPlannerParams::INCLUDE_SHARD_FILTER |
- QueryPlannerParams::NO_BLOCKING_SORT;
+ size_t plannerOpts = QueryPlannerParams::DEFAULT | QueryPlannerParams::NO_BLOCKING_SORT;
+
+ // If we are connecting directly to the shard rather than through a mongos, don't filter out
+ // orphaned documents.
+ if (ShardingState::get(txn)->needCollectionMetadata(txn, nss.ns())) {
+ plannerOpts |= QueryPlannerParams::INCLUDE_SHARD_FILTER;
+ }
// The only way to get a text score is to let the query system handle the projection. In all
// other cases, unless the query system can do an index-covered projection and avoid going to
diff --git a/src/mongo/db/pipeline/pipeline_d.h b/src/mongo/db/pipeline/pipeline_d.h
index a9993c6331b..95a08719b41 100644
--- a/src/mongo/db/pipeline/pipeline_d.h
+++ b/src/mongo/db/pipeline/pipeline_d.h
@@ -32,6 +32,7 @@
#include <memory>
#include "mongo/bson/bsonobj.h"
+#include "mongo/db/namespace_string.h"
namespace mongo {
class Collection;
@@ -79,6 +80,7 @@ public:
static std::shared_ptr<PlanExecutor> prepareCursorSource(
OperationContext* txn,
Collection* collection,
+ const NamespaceString& nss,
const boost::intrusive_ptr<Pipeline>& pPipeline,
const boost::intrusive_ptr<ExpressionContext>& pExpCtx);
@@ -97,6 +99,7 @@ private:
static std::shared_ptr<PlanExecutor> prepareExecutor(
OperationContext* txn,
Collection* collection,
+ const NamespaceString& nss,
const boost::intrusive_ptr<Pipeline>& pipeline,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
const boost::intrusive_ptr<DocumentSourceSort>& sortStage,