mirror of https://github.com/mongodb/mongo
138 lines
6.1 KiB
JavaScript
138 lines
6.1 KiB
JavaScript
/**
|
|
* Utility functions that are common for both mocked and e2e search tests.
|
|
*/
|
|
|
|
/**
|
|
* Checks that the explain object for a sharded search query contains the correct "protocolVersion".
|
|
* Checks 'metaPipeline' and 'sortSpec' if it's provided.
|
|
* * @param {Object} result the results from running coll.explain().aggregate([[$search: ....],
|
|
* ...])
|
|
* @param {string} searchType ex. "$search", "$searchMeta"
|
|
* @param {Object} metaPipeline
|
|
* @param {NumberInt()} protocolVersion To check the value of the protocolVersion, the value
|
|
* returned from explain will be wrapped with NumberInt(). The default value to check is 1 since
|
|
* mongot currently always returns 1 for its protocolVersion.
|
|
* @param {Object} sortSpec
|
|
*/
|
|
export function verifyShardsPartExplainOutput({
|
|
result,
|
|
searchType,
|
|
metaPipeline = null,
|
|
protocolVersion = NumberInt(1),
|
|
sortSpec = null,
|
|
}) {
|
|
// Checks index 0 of 'shardsPart' since $search, $searchMeta need to come first in the pipeline
|
|
assert(result.splitPipeline.shardsPart[0][searchType].hasOwnProperty("metadataMergeProtocolVersion"));
|
|
assert(result.splitPipeline.shardsPart[0][searchType].hasOwnProperty("mergingPipeline"));
|
|
|
|
assert.eq(NumberInt(result.splitPipeline.shardsPart[0][searchType].metadataMergeProtocolVersion), protocolVersion);
|
|
|
|
if (metaPipeline) {
|
|
assert.eq(result.splitPipeline.shardsPart[0][searchType].mergingPipeline, metaPipeline);
|
|
}
|
|
if (sortSpec) {
|
|
assert(result.splitPipeline.shardsPart[0][searchType].hasOwnProperty("sortSpec"));
|
|
assert.eq(result.splitPipeline.shardsPart[0][searchType].sortSpec, sortSpec);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper to create an explain object that getAggPlanStages() can be used on.
|
|
*
|
|
* @param {Object} unionSubExplain The explain output for the $unionWith sub pipeline. Given an
|
|
* unionWithStage, accessed with unionWithStage.$unionWith.pipeline.
|
|
*
|
|
* @returns explain object that getAggPlanStages() can be called to retrieve stages.
|
|
*/
|
|
|
|
export function prepareUnionWithExplain(unionSubExplain) {
|
|
if (
|
|
unionSubExplain.hasOwnProperty("stages") ||
|
|
unionSubExplain.hasOwnProperty("shards") ||
|
|
unionSubExplain.hasOwnProperty("queryPlanner")
|
|
) {
|
|
return unionSubExplain;
|
|
}
|
|
// In the case that the pipeline doesn't have "stages", "shards", or "queryPlanner", the explain
|
|
// output is an array of stages. We return {stages: []} to replicate what a normal explain does.
|
|
assert(
|
|
Array.isArray(unionSubExplain),
|
|
"We expect the input is an array here. If this is not an array, this function needs to be " +
|
|
"updated in order to replicate a non-unionWith explain object. " +
|
|
tojson(unionSubExplain),
|
|
);
|
|
|
|
// The first stage of the explain array should be a initial mongot stage.
|
|
assert(
|
|
Object.keys(unionSubExplain[0]).includes("$_internalSearchMongotRemote") ||
|
|
Object.keys(unionSubExplain[0]).includes("$searchMeta") ||
|
|
Object.keys(unionSubExplain[0]).includes("$vectorSearch"),
|
|
"The first stage of the array should be a mongot stage.",
|
|
);
|
|
|
|
return {stages: unionSubExplain};
|
|
}
|
|
|
|
const mongotStages = ["$_internalSearchMongotRemote", "$searchMeta", "$_internalSearchIdLookup", "$vectorSearch"];
|
|
|
|
/**
|
|
* Validates that the mongot stage from the explain output includes the required execution metrics.
|
|
*
|
|
* @param {Object} stage The object representing a mongot stage ($_internalSearchMongotRemote,
|
|
* $searchMeta, $_internalSearchIdLookup) from explain output.
|
|
* @param {string} stageType ex. "$_internalSearchMongotRemote" , "$searchMeta",
|
|
* "$_internalSearchIdLookup", "$vectorSearch"
|
|
* @param {string} verbosity The verbosity of explain. "nReturned" and "executionTimeMillisEstimate"
|
|
* will not be checked for 'queryPlanner' verbosity "
|
|
* @param {NumberLong} nReturned The number of documents that should be returned in the
|
|
* mongot stage. Optional for "queryPlanner" verbosity.
|
|
* @param {Object} explain The explain object that the stage should contain.
|
|
* @param {Boolean} isE2E True if this function is being called for an e2e test. Since an e2e test
|
|
* uses an actual mongot, we don't know the value of the explain object and cannot check it.
|
|
* @param {NumberLong} numFiltered optional, The number of documents filtered out by the idLookup
|
|
* stage.
|
|
*/
|
|
export function validateMongotStageExplainExecutionStats({
|
|
stage,
|
|
stageType,
|
|
verbosity,
|
|
nReturned = null,
|
|
explain = null,
|
|
isE2E = false,
|
|
numFiltered = null,
|
|
}) {
|
|
assert(mongotStages.includes(stageType), "stageType must be a mongot stage found in mongotStages.");
|
|
assert(stage[stageType], "Given stage isn't the expected stage. " + stageType + " is not found.");
|
|
|
|
const isIdLookup = stageType === "$_internalSearchIdLookup";
|
|
|
|
if (verbosity != "queryPlanner") {
|
|
assert(stage.hasOwnProperty("nReturned"));
|
|
assert.eq(nReturned, stage["nReturned"]);
|
|
assert(stage.hasOwnProperty("executionTimeMillisEstimate"));
|
|
|
|
if (isIdLookup) {
|
|
const idLookupStage = stage["$_internalSearchIdLookup"];
|
|
assert(idLookupStage.hasOwnProperty("totalDocsExamined"), idLookupStage);
|
|
assert.eq(idLookupStage["totalDocsExamined"], nReturned, idLookupStage);
|
|
assert(idLookupStage.hasOwnProperty("totalKeysExamined"), idLookupStage);
|
|
assert.eq(idLookupStage["totalKeysExamined"], nReturned, idLookupStage);
|
|
}
|
|
}
|
|
|
|
// Non $_internalSearchIdLookup mongot stages must contain an explain object.
|
|
if (!isIdLookup) {
|
|
const explainStage = stage[stageType];
|
|
assert(explainStage.hasOwnProperty("explain"), explainStage);
|
|
// We don't know the actual value of the explain object for e2e tests and can't check it.
|
|
if (!isE2E) {
|
|
assert(explain, "Explain is null but needs to be provided for initial mongot stage.");
|
|
assert.eq(explain, explainStage["explain"]);
|
|
if (numFiltered) {
|
|
assert(explainStage.hasOwnProperty("numDocsFilteredByIdLookup"), explainStage);
|
|
assert.eq(explainStage["numDocsFilteredByIdLookup"], numFiltered);
|
|
}
|
|
}
|
|
}
|
|
}
|