SERVER-121320 Combine featureFlagExtensionViewsAndUnionWith with featureFlagExtensionsInsideHybridSearch (#51436)
GitOrigin-RevId: 7167bc3fd8386c072d8ddf956d1fd8403745d720
This commit is contained in:
parent
e7f67a880f
commit
c07b170c29
@ -7,7 +7,7 @@
|
||||
* The stage serializes the view pipeline in its BSON so shards receive it when mongos sends the
|
||||
* pipeline; thus every document (including from shards and merge) has the field.
|
||||
*
|
||||
* @tags: [featureFlagExtensionsAPI, featureFlagExtensionViewsAndUnionWith]
|
||||
* @tags: [featureFlagExtensionsAPI, featureFlagExtensionsInsideHybridSearch]
|
||||
*/
|
||||
|
||||
import {before, describe, it} from "jstests/libs/mochalite.js";
|
||||
|
||||
@ -68,7 +68,7 @@ export function wrapOptionsWithViewsAndUnionWithFeatureFlag(baseOptions) {
|
||||
...baseOptions,
|
||||
setParameter: {
|
||||
...baseOptions.setParameter,
|
||||
featureFlagExtensionViewsAndUnionWith: true,
|
||||
featureFlagExtensionsInsideHybridSearch: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -156,7 +156,7 @@ export function assertExtensionVectorSearchInUnionWithUsed(primaryConn) {
|
||||
}
|
||||
|
||||
export function assertVectorSearchInUnionWithBasedOnFeatureFlag(primaryConn) {
|
||||
if (FeatureFlagUtil.isPresentAndEnabled(primaryConn, "ExtensionViewsAndUnionWith")) {
|
||||
if (FeatureFlagUtil.isPresentAndEnabled(primaryConn, "ExtensionsInsideHybridSearch")) {
|
||||
assertExtensionVectorSearchInUnionWithUsed(primaryConn);
|
||||
} else {
|
||||
assertLegacyVectorSearchInUnionWithUsed(primaryConn);
|
||||
|
||||
@ -280,5 +280,5 @@ withExtensionsAndMongot(
|
||||
// TODO SERVER-123557: Add sharded topology testing.
|
||||
["standalone"],
|
||||
{},
|
||||
{setParameter: {featureFlagExtensionViewsAndUnionWith: false, featureFlagExtensionsInsideHybridSearch: false}},
|
||||
{setParameter: {featureFlagExtensionsInsideHybridSearch: false}},
|
||||
);
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
/**
|
||||
* This test ensures that $search and $searchMeta correctly skip invoking the IFR flag kickback
|
||||
* retry when featureFlagExtensionViewsAndUnionWith is enabled. It tests views, $unionWith on
|
||||
* retry when featureFlagExtensionsInsideHybridSearch is enabled. It tests views, $unionWith on
|
||||
* collections, and $unionWith on views.
|
||||
*
|
||||
* Only tests featureFlagSearchExtension=true (extension path). The legacy $search path behaves
|
||||
* identically regardless of featureFlagExtensionViewsAndUnionWith and is already covered by
|
||||
* identically regardless of featureFlagExtensionsInsideHybridSearch and is already covered by
|
||||
* search_ifr_flag_retry.js.
|
||||
*
|
||||
* @tags: [
|
||||
* featureFlagExtensionsAPI,
|
||||
* featureFlagExtensionViewsAndUnionWith,
|
||||
* featureFlagExtensionsInsideHybridSearch,
|
||||
* featureFlagSearchExtension,
|
||||
* ]
|
||||
*/
|
||||
@ -58,7 +58,7 @@ function runSearchViewTest(conn, shardingTest, isSearchMeta) {
|
||||
|
||||
/**
|
||||
* Runs $search or $searchMeta inside a $unionWith subpipeline on a collection.
|
||||
* No kickback should occur since featureFlagExtensionViewsAndUnionWith is enabled.
|
||||
* No kickback should occur since featureFlagExtensionsInsideHybridSearch is enabled.
|
||||
*/
|
||||
function runUnionWithSearchStageTests(conn, shardingTest, isSearchMeta) {
|
||||
const {coll} = createTestView(conn, shardingTest);
|
||||
@ -92,7 +92,7 @@ function runUnionWithSearchStageTests(conn, shardingTest, isSearchMeta) {
|
||||
|
||||
/**
|
||||
* Runs $search or $searchMeta inside a $unionWith subpipeline targeting a view.
|
||||
* No kickback should occur since featureFlagExtensionViewsAndUnionWith is enabled.
|
||||
* No kickback should occur since featureFlagExtensionsInsideHybridSearch is enabled.
|
||||
*/
|
||||
function runUnionWithOnViewSearchTests(conn, shardingTest, isSearchMeta) {
|
||||
const {coll} = createTestView(conn, shardingTest);
|
||||
@ -126,7 +126,7 @@ function runUnionWithOnViewSearchTests(conn, shardingTest, isSearchMeta) {
|
||||
|
||||
/**
|
||||
* Runs $unionWith targeting a view whose pipeline contains $search or $searchMeta.
|
||||
* No kickback should occur since featureFlagExtensionViewsAndUnionWith is enabled.
|
||||
* No kickback should occur since featureFlagExtensionsInsideHybridSearch is enabled.
|
||||
*/
|
||||
function runUnionWithOnViewWithSearchInViewDefinitionTests(conn, shardingTest, isSearchMeta) {
|
||||
const {testDb, coll} = createTestView(conn, shardingTest);
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* This test ensures that $vectorSearch works against views, within $unionWith on collections,
|
||||
* within $unionWith on views, and inside $rankFusion/$scoreFusion subpipelines, and that the IFR flag kickback retry is invoked to fall back
|
||||
* to legacy vector search when featureFlagExtensionViewsAndUnionWith is disabled.
|
||||
* to legacy vector search when featureFlagExtensionsInsideHybridSearch is disabled.
|
||||
*
|
||||
* @tags: [ featureFlagExtensionsAPI ]
|
||||
*/
|
||||
@ -307,7 +307,6 @@ withExtensionsAndMongot(
|
||||
{shards: kNumShards},
|
||||
{
|
||||
setParameter: {
|
||||
featureFlagExtensionViewsAndUnionWith: false,
|
||||
featureFlagExtensionsInsideHybridSearch: false,
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* This test ensures that $vectorSearch correctly skips invoking the IFR flag kickback retry when
|
||||
* featureFlagExtensionViewsAndUnionWith is enabled. It tests views, $unionWith on collections,
|
||||
* featureFlagExtensionsInsideHybridSearch is enabled. It tests views, $unionWith on collections,
|
||||
* and $unionWith on views.
|
||||
*
|
||||
* It also tests that $rankFusion and $scoreFusion with $vectorSearch subpipelines use
|
||||
* legacy vector search via the IFR kickback retry mechanism when
|
||||
* featureFlagExtensionsInsideHybridSearch is disabled.
|
||||
*
|
||||
* @tags: [ featureFlagExtensionsAPI, featureFlagExtensionViewsAndUnionWith ]
|
||||
* @tags: [ featureFlagExtensionsAPI, featureFlagExtensionsInsideHybridSearch ]
|
||||
*/
|
||||
import {getParameter, setParameterOnAllNonConfigNodes} from "jstests/noPassthrough/libs/server_parameter_helpers.js";
|
||||
import {
|
||||
@ -54,7 +54,7 @@ function runViewVectorSearchTests(conn, mongotMock, featureFlagValue, shardingTe
|
||||
// Get the current feature flag value to determine if we expect extension or legacy $vectorSearch to be used.
|
||||
const expectExtension = getParameter(conn, "featureFlagVectorSearchExtension").value;
|
||||
|
||||
// There should have been no retries since featureFlagExtensionViewsAndUnionWith is enabled.
|
||||
// There should have been no retries since featureFlagExtensionsInsideHybridSearch is enabled.
|
||||
// If the extension is used, we expect extension $vectorSearch; otherwise legacy.
|
||||
// 2 queries (explain + aggregate) per shard.
|
||||
const expectedLegacyDelta = expectExtension ? 0 : 2 * numNodes;
|
||||
@ -85,7 +85,7 @@ function runViewVectorSearchTests(conn, mongotMock, featureFlagValue, shardingTe
|
||||
|
||||
/**
|
||||
* Runs the vector search tests within a $unionWith on a collection.
|
||||
* When featureFlagExtensionViewsAndUnionWith is enabled, no kickback retry should occur.
|
||||
* When featureFlagExtensionsInsideHybridSearch is enabled, no kickback retry should occur.
|
||||
*
|
||||
* @param {Mongo|Object} conn - The connection to use (mongos or mongod).
|
||||
* @param {MongotMock} mongotMock - The mongot mock instance for configuring responses.
|
||||
@ -120,7 +120,7 @@ function runUnionWithVectorSearchTests(conn, mongotMock, featureFlagValue, shard
|
||||
// Get the current feature flag value to determine if we expect extension or legacy $vectorSearch.
|
||||
const expectExtension = getParameter(conn, "featureFlagVectorSearchExtension").value;
|
||||
|
||||
// There should have been no retries since featureFlagExtensionViewsAndUnionWith is enabled.
|
||||
// There should have been no retries since featureFlagExtensionsInsideHybridSearch is enabled.
|
||||
// 1 aggregate query per shard.
|
||||
const expectedLegacyDelta = expectExtension ? 0 : numNodes;
|
||||
const expectedExtensionDelta = expectExtension ? numNodes : 0;
|
||||
@ -145,7 +145,7 @@ function runUnionWithVectorSearchTests(conn, mongotMock, featureFlagValue, shard
|
||||
|
||||
/**
|
||||
* Runs $vectorSearch within a $unionWith on a view.
|
||||
* When featureFlagExtensionViewsAndUnionWith is enabled, no kickback retry should occur.
|
||||
* When featureFlagExtensionsInsideHybridSearch is enabled, no kickback retry should occur.
|
||||
*
|
||||
* @param {Mongo|Object} conn - The connection to use (mongos or mongod).
|
||||
* @param {MongotMock} mongotMock - The mongot mock instance for configuring responses.
|
||||
@ -161,7 +161,7 @@ function runUnionWithOnViewVectorSearchTests(conn, mongotMock, featureFlagValue,
|
||||
const numNodes = shardingTest ? kNumShards : 1;
|
||||
|
||||
// Set up MongotMock cursor for aggregate query.
|
||||
// When querying $unionWith on a view with featureFlagExtensionViewsAndUnionWith enabled,
|
||||
// When querying $unionWith on a view with featureFlagExtensionsInsideHybridSearch enabled,
|
||||
// the mongot command includes viewName and view fields.
|
||||
setUpMongotMockForVectorSearch(mongotMock, {
|
||||
vectorSearchQuery,
|
||||
@ -183,7 +183,7 @@ function runUnionWithOnViewVectorSearchTests(conn, mongotMock, featureFlagValue,
|
||||
// Get the current feature flag value to determine if we expect extension or legacy $vectorSearch.
|
||||
const expectExtension = getParameter(conn, "featureFlagVectorSearchExtension").value;
|
||||
|
||||
// There should have been no retries since featureFlagExtensionViewsAndUnionWith is enabled.
|
||||
// There should have been no retries since featureFlagExtensionsInsideHybridSearch is enabled.
|
||||
// 1 aggregate query per shard.
|
||||
const expectedLegacyDelta = expectExtension ? 0 : numNodes;
|
||||
const expectedExtensionDelta = expectExtension ? numNodes : 0;
|
||||
@ -227,15 +227,15 @@ function runTests(conn, mongotMock, shardingTest = null) {
|
||||
|
||||
// Run hybrid search tests ($rankFusion/$scoreFusion with $vectorSearch subpipelines).
|
||||
// These trigger the IFR kickback retry when featureFlagExtensionsInsideHybridSearch is disabled.
|
||||
setParameterOnAllNonConfigNodes(conn, "featureFlagExtensionsInsideHybridSearch", false);
|
||||
runHybridSearchTests(conn, mongotMock, true, shardingTest);
|
||||
runHybridSearchTests(conn, mongotMock, false, shardingTest);
|
||||
setParameterOnAllNonConfigNodes(conn, "featureFlagExtensionsInsideHybridSearch", true);
|
||||
}
|
||||
|
||||
// We don't have to manually enable featureFlagExtensionViewsAndUnionWith since the test will only run if it's enabled.
|
||||
withExtensionsAndMongot(
|
||||
{"libvector_search_extension.so": {}},
|
||||
runTests,
|
||||
["standalone", "sharded"],
|
||||
{shards: kNumShards},
|
||||
{setParameter: {featureFlagExtensionsInsideHybridSearch: false}},
|
||||
);
|
||||
// featureFlagExtensionsInsideHybridSearch is enabled by default (required by the test tag).
|
||||
// Hybrid search tests dynamically disable it in runTests() since $rankFusion/$scoreFusion
|
||||
// kickback retries only fire when the flag is off.
|
||||
withExtensionsAndMongot({"libvector_search_extension.so": {}}, runTests, ["standalone", "sharded"], {
|
||||
shards: kNumShards,
|
||||
});
|
||||
@ -172,7 +172,7 @@ LiteParsedList DocumentSourceExtensionOptimizable::LiteParsedExpandable::expandI
|
||||
},
|
||||
[&](AggStageAstNodeHandle handle) {
|
||||
outExpanded.emplace_back(std::make_unique<LiteParsedExpanded>(
|
||||
std::string(handle->getName()), std::move(handle), nss));
|
||||
std::string(handle->getName()), std::move(handle), nss, options.ifrContext));
|
||||
});
|
||||
|
||||
return outExpanded;
|
||||
@ -228,7 +228,9 @@ DocumentSourceExtensionOptimizable::LiteParsedExpanded::getFirstStageViewApplica
|
||||
|
||||
void DocumentSourceExtensionOptimizable::LiteParsedExpanded::bindViewInfo(
|
||||
const ViewInfo& viewInfo, const ResolvedNamespaceMap& resolvedNamespaces) {
|
||||
if (!feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
auto hybridSearchFlagEnabled = _ifrContext &&
|
||||
_ifrContext->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (!hybridSearchFlagEnabled) {
|
||||
// Only $vectorSearch and $search/$searchMeta support IFR kickback on views.
|
||||
// All other extension stages are banned on views when the feature flag is disabled.
|
||||
uassert(ErrorCodes::NotImplemented,
|
||||
|
||||
@ -271,13 +271,15 @@ public:
|
||||
public:
|
||||
LiteParsedExpanded(std::string stageName,
|
||||
AggStageAstNodeHandle astNode,
|
||||
const NamespaceString& nss)
|
||||
const NamespaceString& nss,
|
||||
std::shared_ptr<IncrementalFeatureRolloutContext> ifrContext = nullptr)
|
||||
// NOTE: There is no original BSON since this stage is created from an AST node
|
||||
// desugared without BSON.
|
||||
: LiteParsedDocumentSource(BSON(stageName << BSONObj())),
|
||||
_astNode(std::move(astNode)),
|
||||
_properties(_astNode->getProperties()),
|
||||
_nss(nss) {}
|
||||
_nss(nss),
|
||||
_ifrContext(std::move(ifrContext)) {}
|
||||
|
||||
std::unique_ptr<StageParams> getStageParams() const override {
|
||||
return std::make_unique<ExpandedStageParams>(_astNode->clone());
|
||||
@ -328,7 +330,7 @@ public:
|
||||
|
||||
std::unique_ptr<LiteParsedDocumentSource> clone() const override {
|
||||
return std::make_unique<LiteParsedExpanded>(
|
||||
getParseTimeName(), _astNode->clone(), _nss);
|
||||
getParseTimeName(), _astNode->clone(), _nss, _ifrContext);
|
||||
}
|
||||
|
||||
bool hasExtensionVectorSearchStage() const override;
|
||||
@ -360,6 +362,7 @@ public:
|
||||
AggStageAstNodeHandle _astNode;
|
||||
const MongoExtensionStaticProperties _properties;
|
||||
const NamespaceString _nss;
|
||||
std::shared_ptr<IncrementalFeatureRolloutContext> _ifrContext;
|
||||
};
|
||||
|
||||
// Construction of a source or transform stage that expanded from a desugar stage. This stage
|
||||
@ -367,8 +370,10 @@ public:
|
||||
// responsibility comes from the desugar stage it expanded from.
|
||||
static boost::intrusive_ptr<DocumentSourceExtensionOptimizable> create(
|
||||
const boost::intrusive_ptr<ExpressionContext>& expCtx, AggStageAstNodeHandle astNode) {
|
||||
if (expCtx->getInUnionWith() &&
|
||||
!feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
auto ifrCtx = expCtx->getIfrContext();
|
||||
auto hybridSearchFlagEnabled = ifrCtx &&
|
||||
ifrCtx->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (expCtx->getInUnionWith() && !hybridSearchFlagEnabled) {
|
||||
const auto stageName = std::string(astNode->getName());
|
||||
// Throw the IFR retry error for extension $vectorSearch in $unionWith if the feature
|
||||
// flag is not enabled.
|
||||
|
||||
@ -2548,9 +2548,10 @@ void testViewPolicyHelper(const NamespaceString& nss,
|
||||
auto* astNodeImplPtr = static_cast<ConfigurableViewPolicyTestAstNode*>(astNodeImpl.get());
|
||||
auto astNode = new sdk::ExtensionAggStageAstNodeAdapter(std::move(astNodeImpl));
|
||||
auto handle = AggStageAstNodeHandle{astNode};
|
||||
auto ifrContext = std::make_shared<IncrementalFeatureRolloutContext>();
|
||||
|
||||
host::DocumentSourceExtensionOptimizable::LiteParsedExpanded liteParsed(
|
||||
ConfigurableViewPolicyTestAstNode::kStageName, std::move(handle), nss);
|
||||
ConfigurableViewPolicyTestAstNode::kStageName, std::move(handle), nss, ifrContext);
|
||||
|
||||
const auto viewNss = NamespaceString::createNamespaceString_forTest("test.view"_sd);
|
||||
const auto resolvedNss = NamespaceString::createNamespaceString_forTest("test.collection"_sd);
|
||||
@ -2600,9 +2601,10 @@ void runViewPipelineValidatorCallback(const std::vector<BSONObj>& viewPipeline)
|
||||
auto astNodeImpl = std::make_unique<ViewPipelineValidatorTestAstNode>();
|
||||
auto handle =
|
||||
AggStageAstNodeHandle{new sdk::ExtensionAggStageAstNodeAdapter(std::move(astNodeImpl))};
|
||||
auto ifrContext = std::make_shared<IncrementalFeatureRolloutContext>();
|
||||
|
||||
host::DocumentSourceExtensionOptimizable::LiteParsedExpanded liteParsed(
|
||||
ViewPipelineValidatorTestAstNode::kStageName, std::move(handle), nss);
|
||||
ViewPipelineValidatorTestAstNode::kStageName, std::move(handle), nss, ifrContext);
|
||||
|
||||
const auto viewNss = NamespaceString::createNamespaceString_forTest("test.view"_sd);
|
||||
const auto resolvedNss = NamespaceString::createNamespaceString_forTest("test.coll"_sd);
|
||||
@ -2614,7 +2616,8 @@ void runViewPipelineValidatorCallback(const std::vector<BSONObj>& viewPipeline)
|
||||
|
||||
TEST_F(DocumentSourceExtensionOptimizableTest,
|
||||
LiteParsedExpandedGetViewPolicyWithDefaultPrependAndCallback) {
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
|
||||
const auto viewNss = NamespaceString::createNamespaceString_forTest("test.view"_sd);
|
||||
testViewPolicyHelper(_nss,
|
||||
@ -2625,7 +2628,8 @@ TEST_F(DocumentSourceExtensionOptimizableTest,
|
||||
|
||||
TEST_F(DocumentSourceExtensionOptimizableTest,
|
||||
LiteParsedExpandedGetViewPolicyWithDoNothingAndCallback) {
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
|
||||
const auto viewNss = NamespaceString::createNamespaceString_forTest("test.view"_sd);
|
||||
testViewPolicyHelper(_nss,
|
||||
@ -2636,7 +2640,8 @@ TEST_F(DocumentSourceExtensionOptimizableTest,
|
||||
|
||||
TEST_F(DocumentSourceExtensionOptimizableTest,
|
||||
ViewPipelineValidatorAcceptsOnlyMatchAddFieldsSetStages) {
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
|
||||
// Valid: $match and $addFields (and $set) are allowed.
|
||||
runViewPipelineValidatorCallback({BSON("$match" << BSON("x" << 1))});
|
||||
@ -2650,7 +2655,8 @@ TEST_F(DocumentSourceExtensionOptimizableTest,
|
||||
}
|
||||
|
||||
TEST_F(DocumentSourceExtensionOptimizableTest, ViewPipelineValidatorRejectsDisallowedStages) {
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
|
||||
ASSERT_THROWS(runViewPipelineValidatorCallback({BSON("$project" << BSON("x" << 1))}),
|
||||
AssertionException);
|
||||
|
||||
@ -332,8 +332,10 @@ AggregateCommandRequest makeCollectionAndChunksAggregation(OperationContext* opC
|
||||
};
|
||||
|
||||
auto buildUnionWithStage = [&](bool incremental) -> boost::intrusive_ptr<DocumentSource> {
|
||||
// TODO SERVER-120179 Remove the feature flag guard and the createFromBson path.
|
||||
if (feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
auto ifrCtx = expCtx->getIfrContext();
|
||||
auto hybridSearchFlagEnabled = ifrCtx &&
|
||||
ifrCtx->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (hybridSearchFlagEnabled) {
|
||||
auto bsonDoc = Doc{{"$unionWith", buildUnionWithFn(incremental)}}.toBson();
|
||||
auto liteParsed = LiteParsedUnionWith::parse(
|
||||
expCtx->getNamespaceString(), bsonDoc.firstElement(), LiteParserOptions{});
|
||||
|
||||
@ -153,7 +153,10 @@ std::map<std::string, std::unique_ptr<Pipeline>> parseAndValidateRankedSelection
|
||||
|
||||
// If featureFlagExtensionsInsideHybridSearch is not enabled, perform IFR kickback
|
||||
// for any input pipeline that has an extension $vectorSearch or $search stage.
|
||||
if (!feature_flags::gFeatureFlagExtensionsInsideHybridSearch.checkEnabled()) {
|
||||
auto ifrCtx = pExpCtx->getIfrContext();
|
||||
auto hybridSearchFlagEnabled = ifrCtx &&
|
||||
ifrCtx->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (!hybridSearchFlagEnabled) {
|
||||
// TODO SERVER-115791: Implement support for extension $vectorSearch stages in
|
||||
// rankFusion pipelines.
|
||||
search_helpers::throwIfrKickbackIfNecessary(
|
||||
|
||||
@ -141,7 +141,10 @@ std::map<std::string, std::unique_ptr<Pipeline>> parseAndValidateScoredSelection
|
||||
|
||||
// If featureFlagExtensionsInsideHybridSearch is not enabled, perform IFR kickback
|
||||
// for any input pipeline that has an extension $vectorSearch or $search stage.
|
||||
if (!feature_flags::gFeatureFlagExtensionsInsideHybridSearch.checkEnabled()) {
|
||||
auto ifrCtx = pExpCtx->getIfrContext();
|
||||
auto hybridSearchFlagEnabled = ifrCtx &&
|
||||
ifrCtx->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (!hybridSearchFlagEnabled) {
|
||||
// TODO SERVER-117661: Implement support for extension $vectorSearch stages in
|
||||
// scoreFusion pipelines.
|
||||
search_helpers::throwIfrKickbackIfNecessary(
|
||||
|
||||
@ -110,8 +110,11 @@ DocumentSourceContainer unionWithStageParamsToDocumentSourceFn(
|
||||
auto* typedParams = dynamic_cast<UnionWithStageParams*>(stageParams.get());
|
||||
tassert(11786200, "Expected UnionWithStageParams for unionWith stage", typedParams != nullptr);
|
||||
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled by default.
|
||||
if (!feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
// TODO SERVER-121094 Remove when feature flag is removed.
|
||||
auto ifrCtx = expCtx->getIfrContext();
|
||||
auto hybridSearchFlagEnabled = ifrCtx &&
|
||||
ifrCtx->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (!hybridSearchFlagEnabled) {
|
||||
return {DocumentSourceUnionWith::createFromBson(typedParams->getOriginalBson(), expCtx)};
|
||||
}
|
||||
|
||||
|
||||
@ -160,10 +160,12 @@ HybridSearchPipelineBuilder::constructDesugaredOutput(
|
||||
auto unionWithPipeline = Pipeline::create(initialStagesInInputPipeline, pExpCtx);
|
||||
std::vector<BSONObj> bsonPipeline = unionWithPipeline->serializeToBson();
|
||||
|
||||
// TODO SERVER-120179 Remove the feature flag guard and the createFromBson path.
|
||||
// TODO SERVER-121091 This should have been moved into the LiteParsedDesugarer so the
|
||||
// check should be redundant.
|
||||
if (feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
auto ifrCtx = pExpCtx->getIfrContext();
|
||||
auto hybridSearchFlagEnabled = ifrCtx &&
|
||||
ifrCtx->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (hybridSearchFlagEnabled) {
|
||||
auto unionNss = pExpCtx->getUserNss();
|
||||
UnionWithStageParams params(
|
||||
std::move(unionNss), std::move(bsonPipeline), false, true, BSONElement());
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
|
||||
#include "mongo/base/init.h"
|
||||
#include "mongo/db/pipeline/resolved_namespace.h"
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
#include "mongo/db/query/query_feature_flags_gen.h"
|
||||
|
||||
namespace mongo {
|
||||
@ -55,9 +54,10 @@ bool LiteParsedDesugarer::desugar(LiteParsedPipeline* pipeline,
|
||||
// that the subpipeline was modified, we will need to potentially reparse the full pipeline
|
||||
// from LPP - stages with subpipelines should pass the desugared LP subpipelines through
|
||||
// StageParams.
|
||||
// TODO SERVER-120179 Remove the feature flag guard when the feature flag is enabled.
|
||||
// TODO SERVER-121320 Check the value of the hybrid search field using the IFR context.
|
||||
if (feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
// TODO SERVER-121094 Remove when feature flag is removed.
|
||||
auto hybridSearchFlagEnabled = ifrContext &&
|
||||
ifrContext->getSavedFlagValue(feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (hybridSearchFlagEnabled) {
|
||||
auto& subpipelines = stage.getMutableSubPipelines();
|
||||
for (auto& subpipelineLpp : subpipelines) {
|
||||
modified |= LiteParsedDesugarer::desugar(&subpipelineLpp, ifrContext);
|
||||
|
||||
@ -96,8 +96,6 @@ public:
|
||||
|
||||
} // namespace
|
||||
|
||||
// TODO SERVER-121320 Define an IFR context for each test and replace the nullptr callsites in
|
||||
// LiteParsedDesugarer::desugar() with it.
|
||||
class LiteParsedDesugarerTest : public AggregationContextFixture {
|
||||
public:
|
||||
LiteParsedDesugarerTest() : LiteParsedDesugarerTest(_nss) {}
|
||||
@ -202,6 +200,8 @@ protected:
|
||||
extension::sdk::shared_test_stages::MidADescriptor::make()};
|
||||
extension::sdk::ExtensionAggStageDescriptorAdapter _midBDescriptor{
|
||||
extension::sdk::shared_test_stages::MidBDescriptor::make()};
|
||||
std::shared_ptr<IncrementalFeatureRolloutContext> _ifrContext =
|
||||
std::make_shared<IncrementalFeatureRolloutContext>();
|
||||
};
|
||||
|
||||
TEST_F(LiteParsedDesugarerTest, NoopOnEmptyPipeline) {
|
||||
@ -210,7 +210,7 @@ TEST_F(LiteParsedDesugarerTest, NoopOnEmptyPipeline) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 0);
|
||||
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
ASSERT_EQ(lpp.getStages().size(), 0);
|
||||
}
|
||||
@ -223,7 +223,7 @@ TEST_F(LiteParsedDesugarerTest, NoopOnNonExpandableStages) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 2);
|
||||
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
auto& stages = lpp.getStages();
|
||||
ASSERT_EQ(stages.size(), 2);
|
||||
@ -245,7 +245,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsExpandableToHostParseStage) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
auto& stages = lpp.getStages();
|
||||
ASSERT_EQ(stages.size(), 1);
|
||||
@ -262,7 +262,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsExpandableToHostParseStage) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 3);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Expect: [$project, $match, $project].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -282,7 +282,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsExpandableToHostParseStage) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 2);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Expect: [$match, $project].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -301,7 +301,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsExpandableToHostParseStage) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 2);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Expect: [$project, $match].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -326,7 +326,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsExpandToExtAst) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
auto& stages = lpp.getStages();
|
||||
ASSERT_EQ(stages.size(), 1);
|
||||
@ -364,11 +364,11 @@ TEST_F(LiteParsedDesugarerTest, ExpandsExpandToExtAst) {
|
||||
};
|
||||
|
||||
// First desugar pass.
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
checkLiteParsedPipelineShape(lpp);
|
||||
|
||||
// Second desugar pass should be a no-op.
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
checkLiteParsedPipelineShape(lpp);
|
||||
}
|
||||
}
|
||||
@ -385,7 +385,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsSingleExpandToExtParseOnly) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
auto& stages = lpp.getStages();
|
||||
ASSERT_EQ(stages.size(), 1);
|
||||
@ -409,7 +409,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsRecursiveTopToLeaves) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
auto& stages = lpp.getStages();
|
||||
ASSERT_EQ(stages.size(), 4);
|
||||
@ -447,7 +447,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsMixedToMultipleStagesSplicingIntoPipeline
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 3);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Expect [$project, extNoOp, extNoOp, $match, $idLookup, $project].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -486,7 +486,7 @@ TEST_F(LiteParsedDesugarerTest, ExpandsMultipleExpandablesSequentially) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
ASSERT_EQ(lpp.getStages().size(), 2);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Expect [LeafC, LeafD, LeafA, LeafB].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -513,8 +513,8 @@ TEST_F(LiteParsedDesugarerTest, ExpandsMultipleExpandablesSequentially) {
|
||||
}
|
||||
|
||||
TEST_F(LiteParsedDesugarerTest, DesugarsSubpipelineWithExpandableStage) {
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
registerParser(extension::AggStageDescriptorHandle(&_expandToHostParseDescriptor));
|
||||
const auto extStageName =
|
||||
std::string(extension::sdk::shared_test_stages::kExpandToHostParseName);
|
||||
@ -524,7 +524,7 @@ TEST_F(LiteParsedDesugarerTest, DesugarsSubpipelineWithExpandableStage) {
|
||||
LiteParsedPipeline lpp(_nss, {makeLookupWithSubpipeline({BSON(extStageName << BSONObj())})});
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Main pipeline unchanged: [$lookup].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -536,15 +536,12 @@ TEST_F(LiteParsedDesugarerTest, DesugarsSubpipelineWithExpandableStage) {
|
||||
unregisterParser(extStageName);
|
||||
}
|
||||
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
TEST_F(LiteParsedDesugarerTest, SkipsSubpipelineDesugaringWhenFeatureFlagDisabled) {
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith",
|
||||
false};
|
||||
TEST_F(LiteParsedDesugarerTest, SkipsSubpipelineDesugaringWhenIfrContextIsNull) {
|
||||
registerParser(extension::AggStageDescriptorHandle(&_expandToHostParseDescriptor));
|
||||
const auto extStageName =
|
||||
std::string(extension::sdk::shared_test_stages::kExpandToHostParseName);
|
||||
|
||||
// Create [$lookup] with subpipeline [$expandToHostParse]. With the flag disabled, subpipeline
|
||||
// Create [$lookup] with subpipeline [$expandToHostParse]. With a null IFR context, subpipeline
|
||||
// desugaring is skipped, so the subpipeline should remain unchanged.
|
||||
LiteParsedPipeline lpp(_nss, {makeLookupWithSubpipeline({BSON(extStageName << BSONObj())})});
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
@ -563,22 +560,22 @@ TEST_F(LiteParsedDesugarerTest, SkipsSubpipelineDesugaringWhenFeatureFlagDisable
|
||||
}
|
||||
|
||||
TEST_F(LiteParsedDesugarerTest, NoopOnLookupSubpipelineWithNonExpandableStages) {
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
// Create [$lookup] with subpipeline [$match]. No expandable stages, desugar should return
|
||||
// false.
|
||||
LiteParsedPipeline lpp(_nss, {makeLookupWithSubpipeline({BSON("$match" << BSON("a" << 1))})});
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_FALSE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Subpipeline unchanged: [$match].
|
||||
assertSubpipelineStageIsMatch(lpp.getStages()[0].get(), 0, 0);
|
||||
}
|
||||
|
||||
TEST_F(LiteParsedDesugarerTest, DesugarsSubpipelineAndTopLevelExpandableStage) {
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
registerParser(extension::AggStageDescriptorHandle(&_expandToHostParseDescriptor));
|
||||
const auto extStageName =
|
||||
std::string(extension::sdk::shared_test_stages::kExpandToHostParseName);
|
||||
@ -590,7 +587,7 @@ TEST_F(LiteParsedDesugarerTest, DesugarsSubpipelineAndTopLevelExpandableStage) {
|
||||
BSON(extStageName << BSONObj())});
|
||||
ASSERT_EQ(lpp.getStages().size(), 2);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Main pipeline: [$lookup, $match] (expandToHostParse expanded to $match).
|
||||
auto& stages = lpp.getStages();
|
||||
@ -604,8 +601,8 @@ TEST_F(LiteParsedDesugarerTest, DesugarsSubpipelineAndTopLevelExpandableStage) {
|
||||
}
|
||||
|
||||
TEST_F(LiteParsedDesugarerTest, DesugarsAllSubpipelinesInFacetStage) {
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
registerParser(extension::AggStageDescriptorHandle(&_expandToHostParseDescriptor));
|
||||
const auto extStageName =
|
||||
std::string(extension::sdk::shared_test_stages::kExpandToHostParseName);
|
||||
@ -618,7 +615,7 @@ TEST_F(LiteParsedDesugarerTest, DesugarsAllSubpipelinesInFacetStage) {
|
||||
<< BSON_ARRAY(expandStage)))});
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Main pipeline unchanged: [$facet].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -632,8 +629,8 @@ TEST_F(LiteParsedDesugarerTest, DesugarsAllSubpipelinesInFacetStage) {
|
||||
}
|
||||
|
||||
TEST_F(LiteParsedDesugarerTest, DesugarsNestedSubpipelines) {
|
||||
// TODO SERVER-120179 Remove when the feature flag is enabled.
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
registerParser(extension::AggStageDescriptorHandle(&_expandToHostParseDescriptor));
|
||||
const auto extStageName =
|
||||
std::string(extension::sdk::shared_test_stages::kExpandToHostParseName);
|
||||
@ -648,7 +645,7 @@ TEST_F(LiteParsedDesugarerTest, DesugarsNestedSubpipelines) {
|
||||
<< "pipeline" << BSON_ARRAY(lookupStage)))});
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// Main pipeline unchanged: [$unionWith].
|
||||
auto& stages = lpp.getStages();
|
||||
@ -671,7 +668,8 @@ TEST_F(LiteParsedDesugarerTest, DesugarsNestedSubpipelines) {
|
||||
// the lifted content will be [$match] (desugared). If outermost-first, we'd lift
|
||||
// [$expandToHostParse].
|
||||
TEST_F(LiteParsedDesugarerTest, DesugaringOrderInnermostFirst) {
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionViewsAndUnionWith", true};
|
||||
RAIIServerParameterControllerForTest featureFlag{"featureFlagExtensionsInsideHybridSearch",
|
||||
true};
|
||||
registerParser(std::string(kLiftSubpipelineStageName), LiftSubpipelineLiteParsed::parse);
|
||||
registerParser(extension::AggStageDescriptorHandle(&_expandToHostParseDescriptor));
|
||||
const auto extStageName =
|
||||
@ -687,7 +685,7 @@ TEST_F(LiteParsedDesugarerTest, DesugaringOrderInnermostFirst) {
|
||||
LiteParsedPipeline lpp(_nss, pipelineStages);
|
||||
|
||||
ASSERT_EQ(lpp.getStages().size(), 1);
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, nullptr));
|
||||
ASSERT_TRUE(LiteParsedDesugarer::desugar(&lpp, _ifrContext));
|
||||
|
||||
// The lift stage was replaced with its subpipeline contents. With innermost-first ordering,
|
||||
// those contents were desugared before the lift, so we get [$match] not [$expandToHostParse].
|
||||
|
||||
@ -75,8 +75,8 @@ inline bool isExtensionMongotPipeline(
|
||||
}
|
||||
const auto& firstStageBson = pipeline[0];
|
||||
using detail::is;
|
||||
// Note we don't need to worry about/consult 'featureFlagExtensionViewsAndUnionWith' because the
|
||||
// extension will enforce this behavior by toggling its IFR flag and retrying, so thankfully
|
||||
// Note we don't need to worry about/consult 'featureFlagExtensionsInsideHybridSearch' because
|
||||
// the extension will enforce this behavior by toggling its IFR flag and retrying, so thankfully
|
||||
// this is enough, and we don't need to understand what context this BSON appears in (w.r.t.
|
||||
// views or sub-pipelines).
|
||||
if (is<DocumentSourceVectorSearch>(firstStageBson)) {
|
||||
@ -111,10 +111,10 @@ inline bool isMongotPipeline(const std::shared_ptr<IncrementalFeatureRolloutCont
|
||||
if (is<DocumentSourceVectorSearch>(firstStageBson)) {
|
||||
// Return true if the $vectorSearch implementation would be the legacy
|
||||
// DocumentSourceVectorSearch-based implementation. Note we don't need to worry
|
||||
// about/consult 'featureFlagExtensionViewsAndUnionWith' because the extension will enforce
|
||||
// this behavior by toggling 'gFeatureFlagVectorSearchExtension' and retrying, so thankfully
|
||||
// this is enough, and we don't need to understand what context this BSON appears in (w.r.t.
|
||||
// views or sub-pipelines).
|
||||
// about/consult 'featureFlagExtensionsInsideHybridSearch' because the extension will
|
||||
// enforce this behavior by toggling 'gFeatureFlagVectorSearchExtension' and retrying, so
|
||||
// thankfully this is enough, and we don't need to understand what context this BSON appears
|
||||
// in (w.r.t. views or sub-pipelines).
|
||||
return !detail::hasMongotExtension(serverGlobalParams.extensions) ||
|
||||
!ifrContext->getSavedFlagValue(feature_flags::gFeatureFlagVectorSearchExtension);
|
||||
} else if (is<DocumentSourceSearch>(firstStageBson) ||
|
||||
|
||||
@ -412,12 +412,6 @@ feature_flags:
|
||||
default: false
|
||||
incremental_rollout_phase: in_development
|
||||
|
||||
featureFlagExtensionViewsAndUnionWith:
|
||||
description: "Feature flag to enable extension stages on views and in $unionWith."
|
||||
cpp_varname: gFeatureFlagExtensionViewsAndUnionWith
|
||||
default: false
|
||||
fcv_gated: false
|
||||
|
||||
featureFlag2dsphereIndexVersion4:
|
||||
description: "Feature flag to enable v4 of 2dsphereIndexVersion."
|
||||
cpp_varname: gFeatureFlag2dsphereIndexVersion4
|
||||
|
||||
@ -1500,7 +1500,11 @@ Status ClusterAggregate::runAggregate(
|
||||
// these extensions are not eligible to run on views. If we do not implement this
|
||||
// optimization, we will eventually throw the IFR flag kickback retry and end up
|
||||
// restarting ClusterAggregate again.
|
||||
if (!feature_flags::gFeatureFlagExtensionViewsAndUnionWith.isEnabled()) {
|
||||
// TODO SERVER-121094 Remove when feature flag is removed.
|
||||
auto hybridSearchFlagEnabled = ifrContext &&
|
||||
ifrContext->getSavedFlagValue(
|
||||
feature_flags::gFeatureFlagExtensionsInsideHybridSearch);
|
||||
if (!hybridSearchFlagEnabled) {
|
||||
if (ifrContext->getSavedFlagValue(
|
||||
feature_flags::gFeatureFlagVectorSearchExtension)) {
|
||||
state.ifrFlagsToDisableOnRetries.insert(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user